.NET中的并行集合

2023-12-13 05:52:17

作为.NET 4并行扩展的一部分,新的System.Collections.Concurrent命名空间中包含一些新的集合。它们被设计为在含有较少锁的多线程并发操作时是安全的。该命名空间下还包含三个用于对并发操作的集合进行分区的类,但在此我们不讨论它们。

1. IProducerConsumerCollection和BlockingCollection

IProducerConsumerCollection被设计用于BlockingCollection,有三个新的集合实现了该接口。在描述队列和栈时,我说过它们通常用于为稍后的处理存储工作项;生产者/消费者模式是一种并行执行这些工作项的方式。有时只有一个生产者线程创建工作,多个消费者线程执行工作项。在其他情况下,消费者也可以是生产者,例如,网络爬虫(crawler)处理一个Web页面时会发现更多的链接,供后续爬取。

IProducerConsumerCollection是生产者/消费者模式中数据存储的抽象,BlockingCollection以易用的方式包装该抽象,并提供了限制一次缓冲多少项的功能。

BlockingCollection假设没有东西会直接添加到包装的集合中,所有相关方都应该使用包装器来对工作项进行添加和移除。构造函数包含一个重载,不传入IProducerConsumerCollection参数,而使用ConcurrentQueue作为后台存储。

IProducerConsumerCollection只提供了三个特别有趣的方法:ToArrayTryAddTryTake

  1. ToArray将当前集合内容复制到新的数组中,这个数组是集合在调用该方法时的快照。
  2. TryAdd和TryTake都遵循了标准的TryXXX模式,试图向集合添加或移除项,返回指明成功或失败的布尔值。它允许有效的失败模式,降低了对锁的需求。例如在Queue中,要把“验证队列中是否有项”和“如果有项就进行出队操作”这两个操作合并为一个,就需要一个锁——否则Dequeue就可能抛出异常(例如,当队列有且仅有一个项时,两个线程同时判断它是否有项,并且都返回true,这时其中一个线程先执行了出队操作,而另一个线程再执行出队操作时,由于队列已经空了,因此将抛出异常。——译者注)。

BlockingCollection包含一系列重载,允许指定超时和取消标记,可以在这些非阻塞方法之上提供阻塞行为。通常不需要直接使用BlockingCollectionIProducerConsumerCollection,你可以调用并行扩展中使用了这两个类的其他部分。但了解它们还是很有必要的,特别是在需要自定义行为的时候。

2. ConcurrentBag、ConcurrentQueue和ConcurrentStack

  • 框架自带了三个IProducerConsumerCollection的实现。本质上,它们在获取项的顺序上有所不同;队列和栈与它们非并发等价类的行为一致,而ConcurrentBag没有顺序保证。
  • 它们都以线程安全的方式实现了IEnumerableGetEnumerator()返回的迭代器将对集合的快照进行迭代;迭代时可以修改集合,并且改变不会出现在迭代器中。这三个类都提供了与TryTake类似的TryPeek方法,不过不会从集合中移除值。与TryTake不同的是,IProducerConsumerCollection中没有指定TryPeek方法。

3. ConcurrentDictionary<TKey, TValue>

  • ConcurrentDictionary<TKey, TValue>实现了标准的IDictionary<TKey, TValue>接口(但是所有的并发集合没有一个实现了IList),本质上是一个线程安全的基于散列的字典。它支持并发的多线程读写和线程安全的迭代,不过与上节的三个集合不同,在迭代时对字典的修改,可能会也可能不会反映到迭代器上。
  • 它不仅仅意味着线程安全的访问。普通的字典实现基本上可以通过索引器提供添加或更新,通过Add方法添加或抛出异常,但ConcurrentDictionary<TKey, TValue>提供了名副其实的大杂烩。你可以根据前一个值来更新与键关联的值;通过键获取值,如果该键事先不存在就添加;只有在值是你所期望的时候才有条件地更新;以及许多其他的可能性,所有这些行为都是原子的。在开始时都显得很难,但并行团队的Stephen Toub撰写了一篇博客,详细介绍了什么时候应该使用哪一个方法(参见http://mng.bz/WMdW)。

文章来源:https://blog.csdn.net/fwj380891124/article/details/134953586
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。