2008-09-20 44 views

回答

52

更新 - 在.NET 4中,現在有在System.Collections.Concurrent ConcurrentQueue<T>,這裏http://msdn.microsoft.com/en-us/library/dd267265.aspx記錄。有趣的是,它的IsSynchronized方法(正確)返回false。

ConcurrentQueue<T>是一個完全徹底的重寫,創建隊列的副本來枚舉,並使用先進的非鎖定技術,如Interlocked.CompareExchange()Thread.SpinWait()

這個答案的其餘部分仍然相關,因爲它涉及到舊的Synchronize()和SyncRoot成員的消亡,以及爲什麼它們從API的角度來說工作得不好。


按Zooba的評論中,BCL團隊認爲太多的開發者誤解同步的目的(以及在較小程度上,SyncRoot上)

布賴恩Grunkemeyer描述這對BCL團隊博客一對夫婦回到頂端: http://blogs.msdn.com/bclteam/archive/2005/03/15/396399.aspx

關鍵問題是獲取正確的鎖定粒度,其中一些開發人員會天真地使用多個屬性或方法在「同步」集合上並相信他們的代碼是線程安全的。布賴恩用隊列作爲他的榜樣,

if (queue.Count > 0) { 
    object obj = null; 
    try { 
     obj = queue.Dequeue(); 

開發者沒有意識到,計數可能被另一個線程改變出列被調用之前。

強迫開發人員在整個操作中使用顯式鎖定語句意味着防止這種虛假的安全感。

正如Brian所說,刪除SyncRoot的部分原因是它主要是爲了支持Synchronized而引入的,但也因爲在很多情況下鎖定對象有更好的選擇 - 大多數情況下,Queue實例本身,或

private static object lockObjForQueueOperations = new object(); 

的類擁有的隊列實例...

這後一種方法是最安全的,通常,因爲它避免了其他一些常見的陷阱:

正如他們所說,threading is hard,並使它看起來容易可能是危險的。

+0

我不同意你的意見一致。有趣的是,MSDN的鎖定文檔中提到「通常情況下,表達式就是這個」http://msdn.microsoft.com/en-us/library/c5kehkcz%28VS.71%29.aspx – dvogel 2010-08-16 03:07:20

0

(我假設你的意思是隊列<牛逼>的第二個。)

我不能明確回答這個問題,除了IsSynchronized和SyncRoot上屬性(但不同步()明確)從繼承ICollection接口。沒有任何通用集合使用此接口,並且接口不包含SyncRoot。

至於爲什麼它沒有被包括在內,我只能推測它們沒有被用在圖書館設計者所期望的方式中,或者他們只是沒有被足夠用來證明將它們保留在較新的集合中。

7

您可能會發現並行CTP值得檢查;這裏是從誰是把它在一起的傢伙博客條目漂亮的外用:

Enumerating Concurrent Collections

這是不太一樣的東西,但它可能會解決你的問題更大。 (他們甚至使用Queue<T>ConcurrentQueue<T>爲榜樣。)