【发布时间】:2015-06-16 11:47:47
【问题描述】:
我遇到了多个线程正在创建一个 ICollection 对象的情况。 ConcurrentBag 似乎是最好的(?)解决方案,因为 - 1)每个线程都有自己的本地队列,2)线程不需要通信 - 它们是独立的。到目前为止一切顺利,但事实是我需要从此方法返回一个 ISet(在所有生产者终止之后)。即使当前的 ConcurrentBag 实例 IS 不同(由于应用程序的逻辑而得到保证),我仍然需要将其转换为 ISet,例如 HashSet。在这一点上没有更多的生产者。现在真正的问题来了:
当 ConcurrentBag 被迭代时,调用线程会为不在线程本地队列中的 每个 项获取锁吗?或者它会在每个线程中获取一次锁吗?此外,仅迭代袋子和显式地、锁定地调用 bag.Distinct() 之间的内部实现是否存在差异?
【问题讨论】:
-
要回答您问题的第二部分,迭代集合和调用
Distinct都使用相同的机制(即IEnumerable实现),因此不应该有任何差异锁定-明智的 -
没有锁,因为迭代 ConcurrentBag 是在副本上完成的。
-
@shay__ 为什么不为每个生产者创建一个本地
List<T>,并在所有生产者完成后汇总结果? -
@Mateusz 所以——每个线程都会为调用线程创建一个快照来迭代?
-
Distinct()在 ConcurrentBag 上调用GetEnumerator(),因此实际上您将迭代两次。
标签: c# .net multithreading concurrency locking