3 回答

TA貢獻(xiàn)1860條經(jīng)驗(yàn) 獲得超9個(gè)贊
BlockingQueue 的javadoc(LinkedBlockingQueue的超類)聲明:
BlockingQueue
實(shí)現(xiàn)是線程安全的。所有排隊(duì)方法都使用內(nèi)部鎖或其他形式的并發(fā)控制以原子方式實(shí)現(xiàn)其效果。
“原子地”一詞意味著如果兩個(gè)操作(例如a put
和a take
)同時(shí)發(fā)生,那么實(shí)現(xiàn)將確保它們根據(jù)合同行為。效果會(huì)仿佛在put
之前發(fā)生get
,反之亦然。這也適用于邊緣情況,例如具有一個(gè)元素的隊(duì)列示例。
實(shí)際上,由于put
并且get
正在阻塞操作,因此兩個(gè)操作的相對(duì)順序無(wú)關(guān)緊要。與offer
/ poll
或add
/ remove
順序做的事,但你無(wú)法控制它。
請(qǐng)注意,上述內(nèi)容完全基于javadoc所說(shuō)的內(nèi)容。假設(shè)我已正確解釋了javadoc,那么它適用于所有1個(gè) BlockingQueue
實(shí)現(xiàn),無(wú)論它們是使用一個(gè)還是兩個(gè)鎖......或者根本不使用。如果BlockingQueue
實(shí)現(xiàn)不像上面那樣,那就是一個(gè)錯(cuò)誤!
1 - 正確實(shí)現(xiàn)API的所有實(shí)現(xiàn)。這應(yīng)該涵蓋所有Java SE類。

TA貢獻(xiàn)1859條經(jīng)驗(yàn) 獲得超6個(gè)贊
put
實(shí)施一個(gè) LinkedBlockingQueue
public void put(E e) throws InterruptedException { // some lock and node code // the part that matters here try { while (count.get() == capacity) { notFull.await(); } // put the item in the queue. } finally { // not important here }}
基本上,在put
調(diào)用線程wait
中,容量小于最大持續(xù)時(shí)間。
即使將值放在隊(duì)列上的線程抓取與take線程不同的鎖,它也會(huì)等待將其添加到隊(duì)列中,直到隊(duì)列未滿。
take
有一個(gè)類似的實(shí)現(xiàn),notEmpty
而不是notFull
。

TA貢獻(xiàn)1831條經(jīng)驗(yàn) 獲得超10個(gè)贊
經(jīng)過(guò)2天的搜索,我終于明白了...當(dāng)隊(duì)列中只有一個(gè)項(xiàng)目時(shí),根據(jù)LinkedBlocking Queue的設(shè)計(jì),實(shí)際上有兩個(gè)節(jié)點(diǎn):虛擬頭和真實(shí)項(xiàng)目(同時(shí)最后指向它)。確實(shí),put thread和take thread都可以獲得鎖定,但是它們會(huì)修改隊(duì)列的不同部分。
Put線程會(huì)調(diào)用
last = last.next = node; // last points to the only item in queue
拿線程會(huì)打電話
Node<E> h = head;
Node<E> first = h.next; // first also points to the only item in queue
h.next = h;
head = first;
E x = first.item;
first.item = null;
return x;
這兩個(gè)線程的交集是最后指向put線程以及在線程中首先指向的線程。請(qǐng)注意,put thread僅修改last.item并且take thread僅修改first.next。雖然這兩個(gè)線程修改了同一個(gè)對(duì)象實(shí)例,但它們會(huì)修改它的不同成員,并且不會(huì)導(dǎo)致任何線程沖突。
添加回答
舉報(bào)