.NET的ConcurrentDictionary的哪些成员是线程安全的?

时间:2016-07-12 07:54:03

标签: c# .net multithreading concurrency concurrentdictionary

System.Collections.Concurrent.ConcurrentDictionary的MSDN文档说:

  

线程安全

     

ConcurrentDictionary<TKey, TValue>的所有公共成员和受保护成员都是线程安全的,可以从多个线程同时使用。但是,通过其中一个ConcurrentDictionary<TKey, TValue>实现的接口访问的成员,包括扩展方法,不保证是线程安全的,可能需要通过呼叫者。

(强调我的)

这似乎是自相矛盾的。 “所有成员都是线程安全的。但成员[有时]不是线程安全的。”

我确实理解扩展方法当然不能保证是线程安全的。

但是“通过其中一个接口访问”是什么意思? TryGetValueIDictionary<TKey, TValue>接口的成员)线程安全吗?

3 个答案:

答案 0 :(得分:5)

请注意涵盖explicit interface implementations的文档部分。例如。该类实现IDictionary.Add。此方法是该类的公共或受保护成员,但可以通过IDictionary接口访问。正是这些成员不能保证是线程安全的。

答案 1 :(得分:3)

the documentation中有一个特定部分明确表示ConcurrentDictionary<TKey, TValue>中并非一切都是线程安全的:

  

所有这些操作都是原子操作,对ConcurrentDictionary<TKey, TValue>类的所有其他操作都是线程安全的。唯一的例外是接受委托的方法,即AddOrUpdateGetOrAdd。对于字典的修改和写入操作,ConcurrentDictionary<TKey, TValue>使用细粒度锁定来确保线程安全。 (对字典的读取操作是以无锁方式执行的。)但是,这些方法的委托在锁外部调用,以避免在锁定下执行未知代码时可能出现的问题。因此,这些代理执行的代码不受操作原子性的影响。

因此,有一些常规排除项和某些特定于ConcurrentDictionary<TKey, TValue>的情况:

  • AddOrUpdateGetOrAdd上的代表未被称为线程安全问题。
  • 不保证在显式接口实现上调用的方法或属性是线程安全的;
  • 不保证在类上调用的扩展方法是线程安全的;
  • 该类公共成员的所有其他操作都是线程安全的。

答案 2 :(得分:3)

由于Explicit vs Implicit interface implementation

如果查看source code for ConcurrentDictionary<TKey, TValue>,您可能会看到有一些方法明确实现了一个接口(如object IDictionary.this[object key]),虽然内部调用了同一操作的线程安全版本行为可能在未来发生变化。

将其视为责任分工: 如果我(作为一个类)收到ConcurrentDictionary<TKey, TValue>的实例,我知道该实例有责任以线程安全的方式执行操作。

但是,如果我(再次作为一个类)收到IDictionary<TKey, TValue>的实例,那么我应该知道是否应该存在线程安全问题。如果没有这样的问题我只是按原样使用字典,但是如果需要线程安全 我的责任以线程安全的方式执行所有操作。< / p>