我在兩個不同的線程之間使用LinkedBlockingQueue
。一個線程通過add
添加數據,而另一個線程通過take
接收數據。LinkedBlockingQueue的insert和remove方法是否線程安全?
我的問題是,我是否需要同步訪問add
和take
。是LinkedBlockingQueue
的插入和刪除方法線程安全嗎?
我在兩個不同的線程之間使用LinkedBlockingQueue
。一個線程通過add
添加數據,而另一個線程通過take
接收數據。LinkedBlockingQueue的insert和remove方法是否線程安全?
我的問題是,我是否需要同步訪問add
和take
。是LinkedBlockingQueue
的插入和刪除方法線程安全嗎?
是的。從the docs:。
「BlockingQueue實現 線程安全的所有排隊方法 實現原子使用 內部鎖或其他形式的 併發控制它們的影響。然而,大部分 集合操作中的addAll, containsAll,除非在實現中另外指定了其他的 ,所以它是 例如,對於addAll(c) 可能在之後失敗(拋出異常),可能是 原子上是不可能執行僅添加 c中的一些元素。「
是,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個不同的鎖定對象(除了隊列滿/空的邊緣條件期間)。
這個答案提供了一個有效的觀察,但錯過LinkedBlockingQueue的實現者意識到了這個問題並解決了它。詳情在這裏:http://stackoverflow.com/questions/26543807/is-blockingqueue-completely-thread-safe-in-java/26543940#26543940 – 2014-10-24 08:39:10
是的,我同意。 LInkedBlockingQueue提供了比ArrayBlockingQueue更好的併發性,並通過僅同步邊緣條件來維護線程安全。插入和刪除方法已經巧妙地同步於邊緣情況 – 2014-10-24 08:43:43
這個答案是不正確的。 'add'和'take'是線程安全的,可以同時使用,無需額外的同步。 – ens 2016-01-19 17:30:21
簡單的是,它絕對是線程安全的,否則它不會有資格作爲存儲元素的ThreadPoolExecutor的候選人。
只需添加和檢索元素,而不用擔心BlockingQueue的併發性。
實際上不是。不,如果你只是使用add和take,但是如果你使用批量操作,你將不得不同步它而不是簡單的「是」?或者我閱讀文檔錯誤? – cproinger 2012-05-03 13:20:03
@cproinger,不,你不需要同步它,只要你願意處理'addAll'在添加一個項目子集(或類似項目)後拋出一個異常。它取決於你如何定義線程安全。你說得對,批量方法沒有原子性保證。 – 2012-05-04 00:24:16
'remove'也是線程安全的嗎? – q126y 2018-01-24 08:53:07