.NET中的线程安全集合


67

当需要线程安全收集(例如Set)时,如今的标准是什么。我应该自己同步它,还是有一个固有的线程安全集合?


7
安全进行哪些操作?
约翰·桑德斯

2
@John,您知道,添加,阅读等...类似Java的并发集合。
ripper234 2010年

2
您应该使用此信息更新您的问题。您希望对所有内容都具有线程安全性的集合与(例如,对于插入仅具有线程安全性的)集合具有很大的不同。
约翰·桑德斯

1
@John-这如何改变答案?
ripper234 2010年

2
如果答案是.NET 4.0集合,则不是。但是,通常,不同的集合可以具有不同的线程安全性和并行性特征。例如,一个特定的队列可能对多个读取者安全,但对于一个写入者而言却是安全的。
约翰·桑德斯

Answers:


102

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

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

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

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

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


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

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

4
创建线程安全的集合时,您可能更喜欢使用ReaderWriterLockSlim。
桑德洛克(SandRock)2012年

18

在.net 4.0之前的版本中,.Net中的大多数集合都不是线程安全的。您必须自己做一些工作来处理同步:http : //msdn.microsoft.com/zh-cn/library/573ths2x.aspx

引用文章:

可以使用以下任何一种方法使Collections类成为线程安全的:

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

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

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

同步根属性
锁定语句

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

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

阻断收集
并发包
并发队列
并发字典
Ordable分区程序
分区程序
分区程序Ť


4
您锁定的对象应该是一个实例变量,否则就没有意义,因为您始终锁定在新引用上。
Femaref 2010年

1
那是真实的。这只是MSDN页面上有关如何使用锁定代码的示例。
kemiller2002 2010年

4

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


1

除了System.Collections.Concurrent.NET中非常有用的类外,一种也适用于.Net的标准技术(在大多数情况下是很少读取的情况下)(或者如果有频繁但非并发的写操作)也适用于.Net

它具有一些在高并发程序中需要的属性:

  • 集合对象实例本身是不可变的(即线程安全的,可以安全地枚举而不用锁定)
  • 修改可能会花费所需的时间,而读取的性能和并发性不会受到影响
  • 可以通用地实现,以将任何非线程安全的数据结构转换为

限制:如果存在并发写入,则可能必须重试修改,因此并发写入越多,效率就越低。(这是工作中的乐观并发

编辑斯科特·张伯伦(Scott Chamberlain)的评论提醒我,还有另一个限制:如果您的数据结构很大,并且修改频繁发生,那么就内存消耗和所涉及的复制的CPU成本而言,写所有写复制可能会被禁止。


Microsoft通过Microsoft.Bcl.Immutable通过NuGet提供了一组写时复制集合,您可以在此处
Scott Chamberlain

@ScottChamberlain他们的方法比我简单但通用的“写时复制全部”方法复杂得多,因为它们仅复制部分数据。因此,即使更改巨大的数据结构(在复制的CPU成本以及将多个完整副本保存在内存中的内存消耗方面),对于写时全写复制而言效率不高,它们仍然可用。
Evgeniy Berezovsky
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.