首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >ConcurrentDictionary<TKey,TValue>对Dictionary<TKey,TValue>

ConcurrentDictionary<TKey,TValue>对Dictionary<TKey,TValue>
EN

Stack Overflow用户
提问于 2011-03-14 19:32:22
回答 5查看 12.2K关注 0票数 29

As MSDN说

ConcurrentDictionary<TKey, TValue>类表示可以由多个线程并发访问的键值对的线程安全集合。

但我知道,System.Collections.Concurrent类是为PLINQ设计的。

我有Dictionary<Key,Value>,它在服务器中保持在线客户端,当我访问对象时,我通过锁定对象使它线程安全。

在我的情况下,我能安全地用Dictionary<TKey,TValue>代替ConcurrentDictionary<TKey,TValue>吗?更换后性能会提高吗?

这里在第5部分中提到,它是为并行编程设计的。

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

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-03-14 19:37:14

如果你不知道你在锁里做什么,那就说不出来了。

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

代码语言:javascript
运行
复制
lock(lockObject)
{
    foo = dict[key];
}

... // elsewhere

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

然后你就可以把它换掉了(虽然你可能不会看到性能上的任何差别,所以如果它没有坏,就不要修复它)。但是,如果在与字典交互的锁块中执行任何花哨的操作,那么必须确保字典提供了一个可以完成在锁块中所做工作的函数,否则您将得到与以前不同的功能代码。要记住的最重要的事情是,字典只保证以串行方式执行对字典的并发调用;它不能处理代码中有一个操作与字典多次交互的情况。如果ConcurrentDictionary没有考虑到这种情况,则需要您自己的并发控制。

值得庆幸的是,ConcurrentDictionary为更常见的多步操作(如AddOrUpdateGetOrAdd )提供了一些辅助函数,但它们不能涵盖所有情况。如果您发现自己不得不将您的逻辑压缩到这些功能中,那么处理您自己的并发性可能更好。

票数 19
EN

Stack Overflow用户

发布于 2011-03-14 19:40:19

这并不像用Dictionary替换ConcurrentDictionary那么简单,您需要调整代码,因为这些类具有不同行为的新方法,以确保线程安全。

你没有打电话给AddRemove,而是打了TryAddTryRemove。重要的是,使用这些原子化的方法,就好像在第二个调用依赖于第一个调用的结果时,仍然存在争用条件并需要一个lock

票数 5
EN

Stack Overflow用户

发布于 2011-03-14 19:35:46

您可以用Dictionary<TKey, TValue>替换ConcurrentDictionary<TKey, TValue>

但是,对性能的影响可能不是您想要的(如果存在大量的锁定/同步,性能可能会suffer...but,至少您的集合是线程安全的)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5303472

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档