ConcurrentDictionary <TKey,TValue> vs Dictionary <TKey,TValue>

Ars*_*yan 27 c# dictionary concurrent-collections c#-4.0

正如MSDN所说

ConcurrentDictionary<TKey, TValue> Class表示可以由多个线程同时访问的键值对的线程安全集合.

但据我所知,System.Collections.Concurrent课程是为PLINQ设计的.

我有Dictionary<Key,Value>保持服务器中的在线客户端,并且当我有权访问它时通过锁定对象使其成为线程安全的.

我可以放心地取代Dictionary<TKey,TValue>通过ConcurrentDictionary<TKey,TValue>我的情况?更换后性能会提高吗?

这里在第5约瑟夫阿尔巴哈利提到,它专为并行编程

  • 并发集合针对并行编程进行了调整.除了高度并发的场景外,传统的集合在所有集合中都优于它们.
  • 线程安全的集合不保证使用它的代码是线程安全的.
  • 如果在另一个线程正在修改它时枚举并发集合,则不会抛出任何异常.相反,你会得到新旧内容的混合.
  • List没有并发版本.
  • 并发堆栈,队列和包类在内部使用链接列表实现.这使得它们比非并发Stack和Queue类的内存效率更低,但对并发访问更好,因为链表有利于无锁或低锁实现.(这是因为将节点插入链表需要更新几个引用,而将元素插入类似List的结构可能需要移动数千个现有元素.)

Ada*_*son 17

如果不知道你在锁中做了什么,那就不可能说了.

例如,如果您的所有字典访问都如下所示:

lock(lockObject)
{
    foo = dict[key];
}

... // elsewhere

lock(lockObject)
{
    dict[key] = foo;
}
Run Code Online (Sandbox Code Playgroud)

然后你可以将它切换出来(虽然你可能不会看到性能上的任何差异,所以如果没有破坏,不要修复它).但是,如果您在与字典交互的锁定块中执行任何操作,那么您必须确保字典提供单个函数,该函数可以完成您在锁定块中所执行的操作,否则您最终会得到与以前功能不同的代码.要记住的最重要的事情是字典只保证对字典的并发调用以串行方式执行; 它无法处理您的代码中有多个与字典交互的单个操作的情况.这样的情况,如果不考虑ConcurrentDictionary,需要您自己的并发控制.

值得庆幸的是,它ConcurrentDictionary提供了一些辅助函数,用于更常见的多步操作,如AddOrUpdateGetOrAdd,但它们无法涵盖所有​​情况.如果你发现自己不得不把你的逻辑搞砸到这些函数中,那么处理你自己的并发可能会更好.


Dan*_*eny 5

这不是简单的替换DictionaryConcurrentDictionary,你需要去适应你的代码,因为这些类具有不同行为的新方法,以保证线程安全。

例如,而不是调用Add或者Remove,你有TryAddTryRemove。使用这些以原子方式运行的方法很重要,就像您进行两次调用一样,第二次调用依赖于第一个的结果,您仍然会遇到竞争条件并且需要lock.