C# ConcurrentDictionary<;TKey,TValue>;vs字典<;TKey,TValue>;

C# ConcurrentDictionary<;TKey,TValue>;vs字典<;TKey,TValue>;,c#,c#-4.0,dictionary,concurrent-collections,C#,C# 4.0,Dictionary,Concurrent Collections,作为 ConcurrentDictionary类表示可由多个线程并发访问的键值对的线程安全集合 但据我所知,System.Collections.Concurrent类是为PLINQ设计的 我有字典,它将在线客户端保存在服务器中,当我有权访问对象时,我通过锁定对象使其线程安全 在我的情况下,我是否可以安全地将字典替换为ConcurrentDictionary?更换后性能是否会提高 在第5部分中,Joseph Albahari提到它是为并行编程而设计的 并发集合针对并行编程进行了调优。除了高度并

作为

ConcurrentDictionary
类表示可由多个线程并发访问的键值对的线程安全集合

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

我有
字典
,它将在线客户端保存在服务器中,当我有权访问对象时,我通过锁定对象使其线程安全

在我的情况下,我是否可以安全地将
字典
替换为
ConcurrentDictionary
?更换后性能是否会提高

在第5部分中,Joseph Albahari提到它是为并行编程而设计的

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

您可以将
字典
替换为
并发字典


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

虽然我不确定替换的困难,但如果您有任何地方需要在同一个“锁定会话”中访问字典中的多个元素然后你需要修改你的代码


如果Microsoft为读写操作提供了单独的锁,那么它可以提高性能,因为读操作不应该阻止其他读操作。

如果不了解锁中的操作,那么就无法说明

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

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

... // elsewhere

lock(lockObject)
{
    dict[key] = foo;
}
然后你可以把它关掉(虽然你可能看不到性能上的任何差异,所以如果它没有坏,就不要修复它)。但是,如果您在与字典交互的锁块中执行任何有趣的操作,那么您必须确保字典提供了一个函数,可以完成您在锁块中执行的操作,否则您将得到与以前不同的功能代码。要记住的最大一点是,字典只保证以串行方式执行对字典的并发调用;它无法处理代码中的单个操作与字典多次交互的情况。这样的情况,如果没有被
ConcurrentDictionary
考虑,则需要您自己的并发控制


谢天谢地,
ConcurrentDictionary
为更常见的多步骤操作(如
AddOrUpdate
GetOrAdd
)提供了一些帮助函数,但它们不能涵盖所有情况。如果您发现自己必须将逻辑塞进这些函数中,那么最好处理自己的并发性。

是的,您可以安全地进行替换,但是为plinq设计的字典可能有一些额外的代码,用于添加您可能不使用的功能。但性能开销将非常小

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


例如,您没有调用
Add
Remove
,而是调用
TryAdd
TryRemove
。使用这些原子行为的方法很重要,因为如果在第二个调用依赖于第一个调用的结果的情况下进行两次调用,则仍然会有竞争条件,并且需要一个

我不知道System.Collections.Concurrent类是“为PLINQ设计的”-你是从哪里得到这个想法的?@BrokenGlass:也许在某种意义上,lambda和匿名类型是“为LINQ设计的”;它们之所以出现在框架中是因为LINQ,但它们的适用性肯定超越了LINQ。@BrokenGlass和@Adam Robinson,请参见编辑的帖子。这只说明它是为并行编程而优化的,包括PLINQ,但也适用于一般的多线程场景,从TPL到手动生成线程的方法有很多种。好的@BrokenGlass,我认为也有相同的方法。。。谢谢