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

时间:2009-12-22 13:57:03

标签: c# java multithreading concurrent-collections

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

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

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

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

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

3 个答案:

答案 0 :(得分:28)

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

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

答案 1 :(得分:19)

C#提供了多种方式来处理跨多个线程的集合。为了更好地记录这些技术,我建议您从Collections and Synchronization (Thread Safety)开始:

  

默认情况下,Collections类是   一般不是线程安全的。多   读者可以阅读该集合   置信度;但是,任何修改   到集合产生undefined   所有访问的线程的结果   该系列包括读者   线程。

     

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

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

答案 2 :(得分:6)

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

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

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

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

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