3 回答

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

TA貢獻(xiàn)1859條經(jīng)驗 獲得超6個贊
put
實施一個 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ù)時間。
即使將值放在隊列上的線程抓取與take線程不同的鎖,它也會等待將其添加到隊列中,直到隊列未滿。
take
有一個類似的實現(xiàn),notEmpty
而不是notFull
。

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