当我们在linq查询中使用它们时,Concurrent Collections是否是线程安全的?并发收集和不可变集合之间的区别是什么?
答案 0 :(得分:1)
答案 1 :(得分:0)
所有linq方法都通过IEnumerable工作,因此他们使用GetEnumerator方法的实现。从ConcurrentDictionary的源代码中我可以看到Microsoft关于GetEnumerator实现的注释:
从字典返回的枚举器可以安全地与之同时使用 读取和写入字典,但它不代表即时快照 字典。通过调查员公开的内容可能包含修改 在被召唤之后发给字典。
这意味着您可以枚举ConcurrentDictionary,但在枚举期间可能会被其他线程修改,因此您可以通过枚举获得部分更新的字典。为了防止这种情况,您可以通过在枚举之前调用dict.ToArray或使用dict.Keys或dict.Values来获取字典的快照 - 它们会在内部拍摄快照。
ConcurrentStack,ConcurrentQueue和ConcurrentBag的工作方式不同:
枚举表示内容的即时快照 堆栈。它不反映之后对集合的任何更新 被称为。调查员可以安全使用 与堆栈的读取和写入同时发生。
这意味着当您开始迭代时,您将获得当前堆栈/队列的快照,因此其他线程无法更改它。
至于Concurrent和Immutable集合之间的区别,Ariex的答案给你一个很好的解释。