.NET中的线程安全集合

现在什么时候需要一个线程安全的收集标准(例如设置)。 我是否自己同步,还是有一个固有的线程安全集合?

.NET 4.0 Framework在System.Collections.Concurrent命名空间中引入了几个线程安全的集合:

ConcurrentBag <T>
表示一个线程安全的,无序的对象集合。

ConcurrentDictionary <TKey,TValue>
表示可以由多个线程同时访问的键值对的线程安全集合。

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

ConcurrentStack <T>
代表线程安全的后进先出(LIFO)集合。


.NET Framework中的其他集合默认情况下不是线程安全的,需要为每个操作locking:

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

.net 4.0中的大多数集合都不是线程安全的。 你将不得不自己做一些工作来处理同步: http : //msdn.microsoft.com/en-us/library/573ths2x.aspx

从文章引用:

集合类可以使用以下任何方法进行线程安全:

使用Synchronized方法创build一个线程安全的包装器,并通过该包装器专门访问该集合。

如果类没有Synchronized方法,则从该类派生并使用SyncRoot属性实现Synchronized方法。

访问集合时,请使用locking机制,例如C#中的locking语句(Visual Basic中的SyncLock),SyncRoot属性中的locking语句。

同步根属性
locking声明

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

在.net 4.0中引入了System.Collections.Concurrent命名空间

阻止收集
并发袋
并发队列
并行字典
Ordable分区器
分区
分区器T

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

除了System.Collections.Concurrent非常有用的类之外​​,在大多数读取很less更改的情况下(或者,如果存在频繁但非并发的写入)也可以应用于.Net的一种标准技术称为写入时复制

它具有一些高度并发程序中所需的特性:

  • 集合对象实例本身是不可变的(即线程安全,可以安全枚举而不locking)
  • 修改可以花费尽可能多的时间,读取的性能和并发性不受影响
  • 可以一般地实现将任何不是线程安全的数据结构变成一个

限制:如果有并发写入,可能需要重新进行修改,所以并发写入越多,效率越低。 (这是乐观的并发工作)

编辑 Scott Chamberlain的评论提醒我还有另一个限制:如果你的数据结构很庞大,而且经常发生修改,那么在内存消耗和涉及拷贝的CPU成本方面,一次写入复制可能是禁止的。