多个作家,一个读者,哪个集合

时间:2013-02-01 02:37:24

标签: c# multithreading concurrency

我的情况是这样的:

多个线程必须同时写入同一个集合(add和addrange)。物品的顺序不是问题。 当所有线程都完成(加入)并且我回到主线程上时,我需要以foreach样式快速读取所有收集的数据,因为所有线程都完成后不需要实际锁定。

在“过去的日子”中,我可能会在List上使用读写器锁,但是对于新的并发集合,我想知道是否有更好的选择。我只是无法弄清楚哪些并发集合似乎假设读者也在并发线程上。

3 个答案:

答案 0 :(得分:6)

我不相信你想使用System.Collections.Concurrent中的任何收藏品。这些通常有额外的开销以允许并发读取。

除非你有很多争论,否则你可能最好锁定一个简单的List<T>并添加它。

表示,当List重新调整大小时,您将获得少量开销。

但是,在这种情况下我可能会做的只是添加List<T> 每个线程而不是共享,并在处理结束时合并它们,或者只是迭代每个集合中的所有元素。

您可以使用ConcurrentBag然后在准备好阅读时调用.ToArray()GetEnumerator()(绕过每次阅读惩罚),但您可能会发现速度对于简单的List,插入比手动写锁定要慢一些。这实际上取决于争用的数量。 ConcurrentBag非常适合分区,但正如您所指出的,它适用于并发读取写入。

一如既往,以您的特定情况为基准!多线程性能在很大程度上取决于实际使用中的许多事情,诸如数据类型,插入次数等等都会极大地改变结果 - 少数现实值得加倍理论。

答案 1 :(得分:5)

  

物品的顺序不是问题。当所有线程都完成(加入)并且我回到我的主线程上时,我需要读取所有收集的数据

您尚未声明对线程安全集合的要求。共享单个集合没有意义,因为您在写作的同时从未阅读过。所有写作都发生在同一个集合中并不重要,因为顺序无关紧要。也不重要,因为无论如何秩序都是随机的。

所以只需给每个线程自己的集合来填充,不需要锁定。然后逐个迭代它们,不需要锁定。

答案 2 :(得分:4)

试试System.Collections.Concurrent.ConcurrentBag

从集合的描述:

  

表示线程安全,无序的对象集合。

我相信这符合您处理多个线程的条件和不重要的项目顺序,稍后当您回到主线程时,您可以快速预测迭代集合并对每个项目执行操作。