我的情况是这样的:
多个线程必须同时写入同一个集合(add和addrange)。物品的顺序不是问题。 当所有线程都完成(加入)并且我回到主线程上时,我需要以foreach样式快速读取所有收集的数据,因为所有线程都完成后不需要实际锁定。
在“过去的日子”中,我可能会在List上使用读写器锁,但是对于新的并发集合,我想知道是否有更好的选择。我只是无法弄清楚哪些并发集合似乎假设读者也在并发线程上。
答案 0 :(得分:6)
我不相信你想使用System.Collections.Concurrent
中的任何收藏品。这些通常有额外的开销以允许并发读取。
除非你有很多争论,否则你可能最好锁定一个简单的List<T>
并添加它。
但是,在这种情况下我可能会做的只是添加List<T>
每个线程而不是共享,并在处理结束时合并它们,或者只是迭代每个集合中的所有元素。
您可以使用ConcurrentBag
然后在准备好阅读时调用.ToArray()
或GetEnumerator()
(绕过每次阅读惩罚),但您可能会发现速度对于简单的List
,插入比手动写锁定要慢一些。这实际上取决于争用的数量。 ConcurrentBag
非常适合分区,但正如您所指出的,它适用于并发读取和写入。
一如既往,以您的特定情况为基准!多线程性能在很大程度上取决于实际使用中的许多事情,诸如数据类型,插入次数等等都会极大地改变结果 - 少数现实值得加倍理论。
答案 1 :(得分:5)
物品的顺序不是问题。当所有线程都完成(加入)并且我回到我的主线程上时,我需要读取所有收集的数据
您尚未声明对线程安全集合的要求。共享单个集合没有意义,因为您在写作的同时从未阅读过。所有写作都发生在同一个集合中并不重要,因为顺序无关紧要。也不重要,因为无论如何秩序都是随机的。
所以只需给每个线程自己的集合来填充,不需要锁定。然后逐个迭代它们,不需要锁定。
答案 2 :(得分:4)
试试System.Collections.Concurrent.ConcurrentBag
。
从集合的描述:
表示线程安全,无序的对象集合。
我相信这符合您处理多个线程的条件和不重要的项目顺序,稍后当您回到主线程时,您可以快速预测迭代集合并对每个项目执行操作。