2010-06-05 119 views
63

當需要線程安全集合(例如Set)時,現在的標準是什麼。 我是否自己同步它,或者是否存在固有的線程安全集合?.NET中的線程安全集合

+6

操作安全? – 2010-06-05 12:18:54

+2

@John,你知道,正在添加,閱讀等......就像一個Java的併發集合。 – ripper234 2010-06-05 20:50:40

+1

你應該用這些信息更新你的問題。它最大的不同之處在於,您希望集合對於所有內容都是線程安全的,而對於僅用於插入的集合來說,線程安全。 – 2010-06-05 23:38:34

回答

94

的.NET 4.0框架引入了幾個System.Collections.Concurrent Namespace線程安全的集合:

ConcurrentBag<T>
     表示對象的線程安全的,無序的集合。

ConcurrentDictionary<TKey, TValue>
   表示可以由多個線程同時訪問的鍵值對的線程安全集合。

ConcurrentQueue<T>
   表示一個線程安全的先入先出(FIFO)集合。

ConcurrentStack<T>
   代表入先出(LIFO)集合線程安全的最後一次。


.NET Framework中的其他集合不是線程安全的默認情況下,需要鎖定爲每個操作:

lock (mySet) 
{ 
    mySet.Add("Hello World"); 
} 
+3

創建線程安全集合時,您可能更喜歡使用ReaderWriterLockSlim。 – SandRock 2012-08-10 22:05:39

4

.NET 4提供了一組線程安全的集合在System.Collections.Concurrent下

17

.net 4.0中的大多數集合都不是線程安全的。你必須自己做一些工作來處理同步:

集合類可以由使用任何下列 方法線程 安全:

創建http://msdn.microsoft.com/en-us/library/573ths2x.aspx

從文章引用一個使用 同步方法的線程安全封裝器,並通過該封裝器專門訪問 集合。

如果該類沒有 同步方法,則從 類派生並使用SyncRoot屬性實現Synchronized 方法。

訪問 集合時使用的鎖定機構,如C#(爲SyncLock在 的Visual Basic)的 鎖聲明,對SyncRoot上 財產。

Sync Root Property
Lock Statement

Object thisLock = new Object(); 
...... 
lock (thisLock) 
{ 
    // Critical code section 
} 

在。網4.0引入了System.Collections.Concurrent命名空間

Blocking Collection
Concurrent Bag
Concurrent Queue
Concurrent Dictionary
Ordable Partitioner
Partitioner
Partitioner T

+4

你鎖定的對象應該是一個實例變量,否則它沒有意義,因爲你總是鎖定一個新的引用。 – Femaref 2010-06-05 13:21:57

+1

的確如此。這只是MSDN頁面上有關如何使用鎖定代碼的示例。 – kemiller2002 2010-06-05 13:45:21

1

在除了非常有用的類中System.Collections.Concurrent,大多在一個標準技術-read-rare-change sc enarios(或者如果有頻繁但非併發的寫入)也適用於.Net的文件被稱爲Copy-on-write

它有一對夫婦,在高併發程序是理想的特性:

  • 收集對象實例本身是不可變的(即線程安全的,可以安全無鎖列舉)
  • 修改可以採取因爲它想要的,性能和讀取不受影響
  • 可以implemented generically將任何數據結構不是線程安全地連接到一個是
併發儘可能多的時間

限制:如果存在併發寫入,則可能必須重試修改,因此併發寫入越多,其效率越低。 (這是optimistic concurrency工作)

編輯斯科特·張伯倫的評論提醒了我,還有另外一個侷限性:如果你的數據結構是巨大的,而且經常會出現修改,複製,所有的寫時可能都來講望而卻步內存消耗和所涉及的複製的CPU成本。

+0

Microsoft通過[Microsoft.Bcl.Immutable](https://www.nuget.org/packages/Microsoft.Bcl.Immutable)通過NuGet提供了一套寫時複製集合,您可以在此找到更多信息[此處] (http://blogs.msdn.com/b/bclteam/archive/2012/12/18/preview-of-immutable-collections-released-on-nuget.aspx) – 2015-06-11 23:42:05

+0

@ScottChamberlain他們的方式比我的簡單,但通用的「複製全部寫入」方法,因爲它們只複製部分數據。所以它們甚至可以改變巨大的數據結構,這在複製全寫入時效率不高,無論是在複製的CPU成本方面,還是在內存中保存多個完整副本的內存消耗。 – 2015-06-12 00:09:46