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

发布于 2024-08-16 11:26:53 字数 335 浏览 0 评论 0原文

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

为什么没有像 Java 那样的并发集合? (Java 文档)。有些集合看起来是线程安全的,但我不清楚其位置是什么,例如:

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

我不想重新发明轮子! (我不是多线程专家,而且我绝对不会低估这有多困难)。

我希望社区能够提供帮助。

I am trying to get an overview of the thread safety theory behind the collections in C#.

Why are there no concurrent collections as there are in Java? (java docs). Some collections appear thread safe but it is not clear to me what the position is for example with regard to:

  • compound operations,
  • safety of using iterators,
  • write operations

I do not want to reinvent the wheel! (I am not a multi-threading guru and am definitely not underestimating how hard this would be anyway).

I hope the community can help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

天冷不及心凉 2024-08-23 11:26:53

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

当然,就如何处理 .NET 4.0 之前的集合而言,Andrew 的答案是完全正确的 - 对于大多数用途,我只是在访问“正常”共享集合时适当锁定。然而,并发集合使得使用生产者/消费者队列等变得容易。

.NET has had relatively "low level" concurrency support until now - but .NET 4.0 introduces the System.Collections.Concurrent namespace which contains various collections which are safe and useful.

Andrew's answer is entirely correct in terms of how to deal with collections before .NET 4.0 of course - and for most uses I'd just lock appropriately when accessing a "normal" shared collection. The concurrent collections, however, make it easy to use a producer/consumer queue, etc.

小草泠泠 2024-08-23 11:26:53

C# 提供了多种跨多个线程处理集合的方法。为了更好地描述这些技术,我建议您从 集合和同步(线程安全)

默认情况下,Collections 类是
一般不是线程安全的。多种的
读者可以通过以下方式阅读该集
信心;然而,任何修改
到集合产生未定义的
所有访问线程的结果
收藏,包括读者
线程。

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

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

C# offers several ways to work with collections across multiple threads. For a good write-up of these techniques I would recommend that you start with Collections and Synchronization (Thread Safety):

By default, Collections classes are
generally not thread safe. Multiple
readers can read the collection with
confidence; however, any modification
to the collection produces undefined
results for all threads that access
the collection, including the reader
threads.

Collections classes can be made thread
safe using any of the following
methods:

  • Create a thread-safe wrapper using the Synchronized method, and
    access the collection exclusively
    through that wrapper.
  • If the class does not have a Synchronized method, derive from the
    class and implement a Synchronized
    method using the SyncRoot property.
  • Use a locking mechanism, such as the lock statement in C# (SyncLock in
    Visual Basic), on the SyncRoot
    property when accessing the
    collection.
若水微香 2024-08-23 11:26:53

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

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

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

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

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

As Jon Skeet mentioned, there are now "thread safe" collections in the System.Collections.Concurrent namespace in .NET 4.

One of the reason that no concurrent collections exist (at least my guess) in prior .NET Framework versions is that it is very hard to guarantee thread safety, even with a concurrent collection.

(This is not entirely true as some collections offer a Synchronized method to return a thread safe collection from a non-thread safe collection so there are some thread safe collections...)

For example assume one has a thread safe Dictionary - if one only want to to an insert if the Key does not exist one would first query the collection to see if the Key exists, then one would do an insert if the key does not exist. These two operation are not thread safe though, between the query of ContainsKey and the Add operation another thread could have done an insert of that key so there is a race condition.

Inother words the operations of the collection are thread safe - but the usage of it is not necessarily. In this case one would need to transition back to traditional locking techniques (mutex/monitor/semaphore...) to achieve thread safety so the concurrent collection has bought you nothing in terms of multi-threaded safety (but is probably worse for performance).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文