当前的实现混合使用了条带锁(我昨天在https://stackoverflow.com/a/11950835/400547 给某人的回答中建议的技术)并考虑非常非常困难操作不可能导致的情况并发操作的问题或由并发操作引起的问题(其中有很多,但您必须非常确定是否使用它们)。
因此,如果您同时在并发字典上执行多个操作,则以下每种操作都是可能的:
- 甚至没有线程锁定,但一切正常。
- 一些线程锁定,但它们锁定在不同的事物上,并且不存在锁定争用。
- 一个或两个线程相互争用锁,速度变慢,但对性能的影响小于单个锁。
- 一个或两个线程需要将整个事物锁定一段时间(通常用于内部调整大小),这会阻塞所有可能在上述情况 3 中被阻塞的线程,尽管有些线程可以继续运行(那些读取的线程)。李>
这些都不涉及脏读,这只是与锁定模糊相关的问题(我自己的并发字典形式根本不使用锁,也没有脏读)。
此线程安全不适用于您的代码完成的批处理(如果您读取一个值然后写入一个值,则读取的值可能在您完成写入之前已更改),但请注意一些常见情况需要Dictionary 上的几个调用由ConcurrentDictionary 上的单个方法来满足(GetOrAdd 和AddOrUpdate 做的事情将是两个调用Dictionary 所以它们可以原子地完成 - 尽管请注意Func 涉及一些重载,可能会被多次调用)。
因此,ConcurrentDictionary 没有额外的危险,所以你应该选择如下:
如果您将不得不锁定一些与ConcurrentDictionary 提供的不匹配的操作批次,例如:
lock(lockObj)
{
var test = dict[key1];
var test2 = dict[key2];
if(test < test2 && test2 < dict[key3] && SomeOtherBooleanProducer())
dict[key4] = SomeFactoryCall(key4);
}
然后你必须锁定ConcurrentDictionary,虽然可能有一种方法可以将它与它提供的并发支持相结合,但可能不会,所以只需使用Dictionary锁。
否则,这取决于可能有多少并发命中。如果您通常只让一个线程访问字典,但您需要防范并发访问的可能性,那么您绝对应该使用带锁的Dictionary。如果您将有六个或更多线程访问字典的时间段,那么您绝对应该选择ConcurrentDictionary(如果它们可能会访问相同数量的键,请查看我的版本,因为这是我性能更好的一种情况)。
很难说“很少”和“很多”线程之间的中间点在哪里。我会说,如果定期有两个以上的线程,那么请使用ConcurrentDictionary。如果不出意外,在项目的整个生命周期中,并发需求往往会增加而不是减少。
编辑:要回答您给出的一个作者和一个读者的特定情况,根本不会有任何阻塞,因为这与多个读者和一个作者在@上是安全的原因大致相同987654336@,尽管ConcurrentDictionary 在几个方面超越了这一点。