ConcurrentDictionary
的文档没有明确的状态,所以我想我们不能指望代理 valueFactory
和 updateValueFactory
让它们的执行同步(分别来自GetOrAdd()和AddOrUpdate()操作)。
所以,我认为我们无法在其中实现需要并发控制的资源,而无需手动实现我们自己的并发控制,可能只是在代理上使用[MethodImpl(MethodImplOptions.Synchronized)]
。
我是对的吗?或者ConcurrentDictionary
是线程安全的事实我们可以预期对这些代理的调用会自动同步(线程安全)吗?
答案 0 :(得分:34)
是的,您是对的,ConcurrentDictionary
未同步用户代理。如果您需要那些同步,这是您的责任。
MSDN本身说:
此外,尽管ConcurrentDictionary的所有方法都是 线程安全,并非所有方法都是原子的,特别是GetOrAdd和 AddOrUpdate。传递给这些方法的用户委托是 在字典的内部锁外部调用。 (这样做是为了 防止未知代码阻塞所有线程。)
See "How to: Add and Remove Items from a ConcurrentDictionary
这是因为ConcurrentDictionary
不知道你提供的代理会做什么或者它的性能,所以如果它试图锁定它们,它可能会对性能产生负面影响并破坏ConcurrentDictionary的值。
因此,如果有必要,用户有责任同步他们的代理。上面的MSDN链接实际上有一个很好的例子,说明它做了什么,不做什么。
答案 1 :(得分:25)
这些代表不仅没有同步,而且甚至不能保证只发生一次。事实上,每次调用AddOrUpdate
时,它们都可以执行多次。
例如,AddOrUpdate
的算法看起来像这样。
TValue value;
do
{
if (!TryGetValue(...))
{
value = addValueFactory(key);
if (!TryAddInternal(...))
{
continue;
}
return value;
}
value = updateValueFactory(key);
}
while (!TryUpdate(...))
return value;
请注意这里的两件事。
所以你需要确保做两件事。