2011-03-14 71 views
25

由于MSDN saysConcurrentDictionary <TKey,TValue> VS字典<TKey,TValue>

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

但我知道,System.Collections.Concurrent类是专为PLINQ。

我有Dictionary<Key,Value>这使上线的客户端服务器,我让线程通过锁定目标,当我有机会获得它的安全。

我可以放心地在我的情况下ConcurrentDictionary<TKey,TValue>更换Dictionary<TKey,TValue>?更换后性能会有所提高吗?

Here在第5部分约瑟夫阿尔巴哈利提到,它设计成用于并行编程

  • 的并发集合被调谐为并行编程。除了高度并发的场景外,传统系列的表现都优于它们。
  • 线程安全的集合不保证使用它的代码是线程安全的。
  • 如果枚举一个并发收集,而另一个线程正在修改它,则不会抛出异常。相反,您会混合使用新旧内容。
  • List没有并发版本。
  • 并发堆栈,队列和包类是内部实现的链表。这使得它们的内存效率低于非并发栈和队列类,但对于并发访问更好,因为链表有利于锁定免费或低锁的实现。 (这是因为插入节点到链表需要更新,只是一对夫妇的参考,同时将元素插入一个列表状结构可能需要移动目前数以千计的元素。)
+0

我不知道System.Collections.Concurrent类是“为PLINQ设计的”这个事实 - 你从哪里得到这个想法? – BrokenGlass 2011-03-14 19:38:52

+0

@BrokenGlass:也许在lambda和匿名类型是“为LINQ设计”的意义上;他们由于* LINQ而成为框架*,但他们肯定具有超越它的适用性。 – 2011-03-14 19:40:05

+0

@BrokenGlass和@Adam Robinson,请参阅编辑后文章 – 2011-03-14 20:01:55

回答

16

不知道更多关于你的锁内做什么,那么就很难说。

举例来说,如果你所有的字典访问看起来是这样的:

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

... // elsewhere 

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

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

谢天谢地,ConcurrentDictionaryAddOrUpdateGetOrAdd等更常见的多步操作提供了一些辅助函数,但它们不能涵盖所有情况。如果你发现自己不得不努力将自己的逻辑变为这些功能,那么处理自己的并发可能会更好。

1

您可以ConcurrentDictionary<TKey, TValue>取代Dictionary<TKey, TValue>

对性能的影响可能不是你想要什么,但(如果有大量的锁定/同步的,性能可能会受到影响......但至少你的收藏是线程安全的)。

1

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

如果微软已经给读单独的锁和写它可以给更高的性能,因为读操作不会阻碍其他读取操作。

0

是的,您可以安全地更换,但为plinq设计的字典可能会有一些额外的代码,用于您可能不会使用的附加功能。但是性能开销稍微小一点。

3

这不像将Dictionary替换为ConcurrentDictionary那么简单,您需要修改代码,因为这些类具有行为不同的新方法,以确保线程安全。例如,您不必拨打AddRemove,您有TryAddTryRemove。使用这些原子方法的方法很重要,就好像你打了两个电话,其中第二个电话依赖于第一个电话的结果,你仍然有竞争条件,需要lock

相关问题