2010-06-05 85 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