一个
ConcurrentDictionary
在需要多个线程同时安全访问一个高性能字典时非常有用。相较于使用
lock
保护的标准
Dictionary
,因为其粒度更小的锁定实现,它在重载情况下更加高效。
ConcurrentDictionary
内部维护了多个锁,而不是所有线程竞争一个单一锁,从而最大限度地减少争用并限制成为瓶颈的可能性。
尽管具有这些良好特性,但使用
ConcurrentDictionary
的最佳选项场景实际上非常有限,原因如下:
1.
ConcurrentDictionary
提供的线程安全保证仅限于保护其内部状态。就是这样。如果想执行稍微复杂一点的操作(例如将字典和另一个变量更新为原子操作),就会遇到麻烦。这对于
ConcurrentDictionary
不是支持的方案。即使保护其包含的元素(如果它们是可变对象)也不受支持。如果尝试使用
AddOrUpdate
方法更新其中一个值,则字典将受到保护,但值不会受到保护。在此上下文中,“更新”意味着用另一个值替换现有值,而不是修改现有值。
2. 当你想要使用
ConcurrentDictionary
时,通常有更好的可用选择,这些选择不涉及共享状态,这正是
ConcurrentDictionary
的本质。无论其锁定方案多么有效,都很难击败一个根本没有共享状态、每个线程独立执行无干扰的架构。遵循此原则的常用库包括
PLINQ 和
TPL Dataflow 库。以下是 PLINQ 示例:
Dictionary<string, Product> dictionary = productIDs
.AsParallel()
.Select(id => GetProduct(id))
.ToDictionary(product => product.Barcode);
不需要预先创建一个字典,然后由多个线程同时填充值。相反,您可以信任PLINQ使用更有效的策略来生成字典,包括对初始工作负载进行分区,并将每个分区分配给不同的工作线程。单个线程最终会聚合部分结果并填充字典。
Dictionary
和何时应该使用ConcurrentDictionary
,鉴于你已经找到了这些信息,那么你就知道何时应该使用其中的一个而不是另一个。 - ServyConcurrentDictionary
。 - Scott ChamberlainSystem.Collections.Concurrent
命名空间都是为此而设计的。 - JonesopolisTask
也应该能够与ConcurrentDictionary
一起使用。 - hyankov