ConcurrentDictionary<TKey, TValue>
Class表示可由多个线程同时访问的键值对的线程安全集合。
但据我所知,System.Collections.Concurrent
类是为PLINQ设计的。
我有Dictionary<Key,Value>
在服务器中保留在线客户端,并且当我有权访问它时,我通过锁定对象使其成为线程安全。
在我的情况下,我可以安全地将Dictionary<TKey,TValue>
替换为ConcurrentDictionary<TKey,TValue>
吗?更换后性能会提高吗?
Here Joseph Albahari提到它是为并行编程而设计的
答案 0 :(得分:16)
如果不知道你在锁中做了什么,那就不可能说了。
例如,如果您的所有词典访问都是这样的:
lock(lockObject)
{
foo = dict[key];
}
... // elsewhere
lock(lockObject)
{
dict[key] = foo;
}
然后你可以将它切换出来(虽然你可能不会看到性能上的任何差异,所以如果没有破坏,不要修复它)。但是,如果您在与字典交互的锁定块中执行任何操作,那么您必须确保字典提供单个函数,该函数可以完成您正在执行的操作在锁定块内,否则您将得到与以前功能不同的代码。要记住的最重要的事情是字典只保证对字典的并发调用以串行方式执行;它无法处理您在 代码中单个操作的情况,该代码多次与字典交互。这种情况,如果没有ConcurrentDictionary
解释,则需要你自己的并发控制。
值得庆幸的是,ConcurrentDictionary
为更常见的多步操作提供了一些辅助函数,例如AddOrUpdate
或GetOrAdd
,但它们无法涵盖所有情况。如果你发现自己不得不把你的逻辑搞砸到这些函数中,那么处理你自己的并发可能会更好。
答案 1 :(得分:3)
这不像用Dictionary
替换ConcurrentDictionary
那么简单,您需要调整代码,因为这些类具有不同行为的新方法,以保证线程安全。
例如,您没有致电Add
或Remove
,而是TryAdd
和TryRemove
。重要的是你使用这些原子行为的方法,就像你进行两次调用,其中第二次依赖于第一次的结果,你仍然会有竞争条件,需要lock
。
答案 2 :(得分:1)
您可以将Dictionary<TKey, TValue>
替换为ConcurrentDictionary<TKey, TValue>
。
对性能的影响可能不是你想要的(如果有很多锁定/同步,性能可能会受到影响......但至少你的集合是线程安全的。)
答案 3 :(得分:1)
虽然我不确定替换困难,但如果您在同一个“锁定会话”中需要访问字典中的多个元素,则需要修改代码。
如果Microsoft为读写提供了单独的锁,它可以提高性能,因为读操作不应该阻止其他读操作。
答案 4 :(得分:0)
是的,您可以安全地替换,但是为plinq设计的字典可能有一些额外的代码,用于添加您可能不使用的功能。但性能开销将略微很小。