2010-04-23 41 views

回答

45

是的。從the docs:。

「BlockingQueue實現 線程安全的所有排隊方法 實現原子使用 內部鎖或其他形式的 併發控制它們的影響。然而,大部分 集合操作中的addAll, containsAll,除非在實現中另外指定了其他的 ,所以它是 例如,對於addAll(c) 可能在之後失敗(拋出異常),可能是 原子上是不可能執行僅添加 c中的一些元素。「

+0

實際上不是。不,如果你只是使用add和take,但是如果你使用批量操作,你將不得不同步它而不是簡單的「是」?或者我閱讀文檔錯誤? – cproinger 2012-05-03 13:20:03

+0

@cproinger,不,你不需要同步它,只要你願意處理'addAll'在添加一個項目子集(或類似項目)後拋出一個異常。它取決於你如何定義線程安全。你說得對,批量方法沒有原子性保證。 – 2012-05-04 00:24:16

+0

'remove'也是線程安全的嗎? – q126y 2018-01-24 08:53:07

8

是,BlockingQueue方法add()take()是線程安全的,但與別不同的

add()take()方法使用2個不同的ReentrantLock對象。

add()方法使用

private final ReentrantLock putLock = new ReentrantLock(); 

take()方法使用

private final ReentrantLock takeLock = new ReentrantLock(); 

因此,爲了add()方法同時訪問是同步的。同樣,對take()方法的同時訪問是​​。

但是,同時訪問和add()take()方法沒有​​,因爲它們使用的是2個不同的鎖定對象(除了隊列滿/空的邊緣條件期間)。

+3

這個答案提供了一個有效的觀察,但錯過LinkedBlockingQueue的實現者意識到了這個問題並解決了它。詳情在這裏:http://stackoverflow.com/questions/26543807/is-blockingqueue-completely-thread-safe-in-java/26543940#26543940 – 2014-10-24 08:39:10

+0

是的,我同意。 LInkedBlockingQueue提供了比ArrayBlockingQueue更好的併發性,並通過僅同步邊緣條件來維護線程安全。插入和刪除方法已經巧妙地同步於邊緣情況 – 2014-10-24 08:43:43

+0

這個答案是不正確的。 'add'和'take'是線程安全的,可以同時使用,無需額外的同步。 – ens 2016-01-19 17:30:21

0

簡單的是,它絕對是線程安全的,否則它不會有資格作爲存儲元素的ThreadPoolExecutor的候選人。

只需添加和檢索元素,而不用擔心BlockingQueue的併發性。