ConcurrentDictionary Object - 通过不同的线程读取和写入

Ran*_*der 10 c# multithreading thread-safety

我想在我的应用程序中使用ConcurrentDictionary,但首先我需要确保我正确理解它是如何工作的.在我的应用程序中,我将有一个或多个线程写入或删除字典.而且,我将有一个或多个从字典中读取的线程.潜在地,所有这些都在同一时间.

我是否正确,ConcurrentDictionary的实现负责处理所有必需的锁定,并且我不需要提供自己的锁定?换句话说,如果一个线程正在写入或删除字典,那么读取线程(或另一个写入线程)将被阻止,直到更新或删除完成为止?

非常感谢.

Jon*_*nna 8

当前的实现使用条带锁的混合(我昨天在/sf/answers/836558481/的答案中提出的技术)并且非常认真地考虑操作不可能导致的情况并发操作引起的问题或有问题(这些问题很多,但你必须非常肯定,如果你使用它们).

因此,如果您同时在并发字典上执行了多个操作,则以下每个操作都是可能的:

  1. 没有线程甚至锁定,但一切都正确.
  2. 一些线程锁定,但它们锁定不同的东西,并且没有锁争用.
  3. 一个或两个线程彼此之间存在锁争用,并且速度变慢,但对性能的影响小于单个锁的影响.
  4. 一个或两个线程需要将整个事物锁定一段时间(通常用于内部调整大小),这会阻止在上面的情况3中可能被阻塞的所有线程,尽管有些线程可以继续(那些读取).

这些都不涉及脏读,这只是与锁定有关的问题(我自己的并发字典形式根本不使用锁,也没有脏读).

此线程安全不适用于您的代码完成的批处理(如果您读取一个值然后写入一个值,读取的值可能在您完成写入之前已经更改),但请注意一些常见情况需要一对在通话的Dictionary单方法照顾上ConcurrentDictionary(GetOrAddAddOrUpdate做的事情,是两个电话用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);
}
Run Code Online (Sandbox Code Playgroud)

然后你必须锁定ConcurrentDictionary,虽然可能有一种方法可以将它与支持并发的方式结合起来,但可能不会,所以只需使用Dictionary锁.

否则它归结为可能会有多少并发命中.如果你大多只有一个线程打到字典,但你需要防止并发访问的可能性,那么你肯定应该Dictionary使用锁.如果你打算有六个或更多线程进入字典的时间段,那么你一定应该去ConcurrentDictionary(如果他们可能会使用相同的少量键,那么请看看我的版本,因为那是我有更好表现的一种情况).

很难说"少数"和"多"线程之间的中间位置.我会说,如果定期有两个以上的线程,那就去吧ConcurrentDictionary.如果不出意外,并发性的要求往往会在项目的整个生命周期中增加,而不是减少.

编辑:要回答你给出的一个作家和一个读者的特定情况,根本就没有任何阻止,因为这对于多个读者和一个作者是安全的大致相同的原因是安全的Hashtable,尽管ConcurrentDictionary超出了在几个方面.


Jon*_*eet 6

换句话说,如果一个线程正在写入或删除字典,那么读取线程(或另一个写入线程)将被阻止,直到更新或删除完成为止?

我不相信它会阻止 - 它会安全.不会有任何腐败 - 你只会在阅读是否看到写入方面有竞争.

有关并发集合的无锁定常见问题解答:

ConcurrentDictionary<TKey,TValue>在添加或更新字典中的数据时使用细粒度锁定,但对于读取操作它完全没有锁定.通过这种方式,它针对从字典中读取最频繁操作的情况进行了优化.

  • @RandyMinder`ConcurrentDictionary`仅保证***操作安全.你可以以对代码不是线程安全的方式使用`ConcurrentDictionary`.例如`foreach(并发字典中的var对)DoSomethingWithPair(pair);`在您的应用中可能是也可能不是线程安全的. (4认同)