保证记录/隐含记录/未记录的行为

时间:2014-06-08 13:49:08

标签: c# .net concurrentdictionary

查看ConcurrentDictionary文档,它说明如下:

  

表示可以的线程安全的键/值对集合   由多个线程同时访问。

现在阅读本文时,我认为我可以调用ConcurrentDictionary API中的任何方法,它将是线程安全的...但是这意味着包含显式实现,我是否有这种保证?

我的例子是如果我想要一个原子操作从ConcurrentDictionary中删除一个项,如果它的值是某个值。

所以我可以这样做:

var concurrentDictionary = new ConcurrentDictionary<string, string>();
concurrentDictionary.TryAdd("hey", "ho");

((ICollection<KeyValuePair<string, string>>) concurrentDictionary).Remove(new KeyValuePair<string, string>("hey", "ho"));

现在我查看了源代码并且该操作既是原子的又是线程安全的,但事实上它不在ConcurrentDictionary API上意味着我不应该使用它...或者也许我正在使用它集合做我不应该做的事情。

我可以更进一步,编写以下扩展方法:

public static boolean TryRemove(this ICollection<KeyValuePair<TKey, TValue>> collection, TKey key, TValue value)
{
    return collection.Remove(new KeyValuePair<TKey, TValue>(key, value));
}

这将出现在ConcoreDictionary的Intellisense中,因为它实现了ICollection接口,许多开发人员甚至可能都不知道有什么不妥(如果真的有什么?!)

修改 我所说的“隐式文档”是ConcurrentDictionary实现了一组接口。它的文档说它的线程是安全的,但是没有声明它是否仅用于该页面上列出的方法,但暗示实例上的所有操作都是安全的。

2 个答案:

答案 0 :(得分:0)

这是关于记录行为的问题。通常,您只能依靠记录的行为来实际持有。其他行为可以随时改变(在运行时,在应用程序运行之间,在框架补丁级别之间......)。

如果您可以在文档中找到这是安全的参考,那么您可以这样做。

如果没有,我一般都会非常小心。另一方面,ConcurrentDictionary是核心类型,BCL团队将极端兼容性标准应用于其工作。即使在生产应用程序中,如果没有记录,我也可以这样做。他们非常小心,即使在主要框架版本之间也不会破坏呼叫者。

由于这些兼容性保证,这是一种核心类型,我可以从source code中获取知识。

答案 1 :(得分:0)

通过执行您描述的内容,您不会破坏ConcurrentDictionary的原子性。

您可能会在并发字典中导致所有存储桶的不必要锁定。 (通过某种方式将其作为集合访问)

这会杀死字典中的“并发”部分,并且效率低于仅使用锁定的普通字典。

ConcurrentDictionary的很棒的部分并不是它是原子的 - 它可以很容易地用锁完成,它是并发的,这意味着多个线程可以原子地写入它而不必相互等待。

一旦你对此有了更好的认识,你就会欣赏GetOrAdd,TryRemove和TryUpdate这样的东西,因为它们允许明确地转换到状态 - 即使你不确定以前的状态。