为什么C#中没有并发集合?

And*_*rew 15 c# java multithreading concurrent-collections

我试图概述C#中集合背后的线程安全理论.

为什么Java中没有并发集合?(java docs).一些集合看起来是线程安全的,但我不清楚这个位置是什么,例如关于:

  • 复合作业,
  • 使用迭代器的安全性,
  • 写操作

我不想重新发明轮子!(我不是一个多线程大师,绝对不会低估这有多难).

我希望社区可以提供帮助.

Jon*_*eet 29

到目前为止,.NET已经具有相对"低级"的并发支持 - 但.NET 4.0引入了System.Collections.Concurrent包含各种安全且有用的集合的命名空间.

安德鲁的答案在.NET 4.0之前如何处理集合方面是完全正确的 - 对于大多数用途,我只是在访问"普通"共享集合时适当锁定.但是,并发集合使得使用生产者/消费者队列等变得容易.


And*_*are 19

C#提供了多种方式来处理跨多个线程的集合.为了更好地记录这些技术,我建议您从集合和同步(线程安全)开始:

默认情况下,Collections类通常不是线程安全的.多位读者可以放心地阅读该系列; 但是,对集合的任何修改都会为访问集合的所有线程(包括读取器线程)生成未定义的结果.

可以使用以下任何方法使集合类成为线程安全的:

  • 使用Synchronized方法创建一个线程安全的包装器,并通过该包装器专门访问该集合.
  • 如果类没有Synchronized方法,则从类派生并使用SyncRoot属性实现Synchronized方法.
  • 访问集合时,在SyncRoot属性上使用锁定机制(如C#中的lock语句(Visual Basic中的SyncLock)).

  • 另见:http://blogs.msdn.com/ericlippert/archive/2008/01/21/immutability-in-c-part-nine-academic-plus-my-avl-tree-implementation.aspx其中Eric Lippert在某种程度上讨论了不可变集合,特别是在并发访问方面. (4认同)

sar*_*ret 6

正如Jon Skeet所提到的,.NET 4中的System.Collections.Concurrent命名空间中现在有"线程安全"集合.

在以前的.NET Framework版本中不存在并发集合(至少我的猜测)的原因之一是即使使用并发集合也很难保证线程安全.

(这不完全正确,因为一些集合提供了一个Synchronized方法来从非线程安全集合返回线程安全集合,因此有一些线程安全集合......)

例如,假设一个人有一个线程安全的字典 - 如果一个人只想要一个插入,如果Key不存在,则首先查询该集合以查看该Key是否存在,然后如果该密钥不存在则进行插入.这两个操作不是线程安全的,但是在ContainsKey的查询和Add操作之间,另一个线程可能已经完成了该键的插入,因此存在竞争条件.

换句话说,集合的操作是线程安全的 - 但它的使用不一定.在这种情况下,需要转换回传统的锁定技术(互斥锁/监视器/信号量......)以实现线程安全性,因此并发收集在多线程安全性方面没有给您带来任何好处(但可能性能更差) .