【问题标题】:Is multi-level ConcurrentDictionary still thread-safe?多级 ConcurrentDictionary 仍然是线程安全的吗?
【发布时间】:2011-02-09 11:07:38
【问题描述】:

我有这样定义的四级数据结构:

Dictionary<Type1, Dictionary<Type2, Dictionary<Type3, List<Type4>>>>

整个事情都封装在一个类中,该类也维护线程安全。目前它只是在读取/操作数据时锁定整个集合(读取比写入更常见几个数量级)。

我正在考虑将Dictionary 替换为ConcurrentDictionary,将List 替换为ConcurrentBag(其项目不必订购)。

如果我这样做,我是否可以消除锁并确保并发集合能够正确完成它们的工作?

【问题讨论】:

  • 并发集合正常工作,但这种数据结构看起来很疯狂!
  • 您确定不想要ConcurrentDictionary&lt;Tuple&lt;TKey1,TKey2,TKey2&gt;,TValue&gt;
  • @CodeInChaos 查看我对 Mania 回答的评论。

标签: c# .net .net-4.0 concurrency parallel-extensions


【解决方案1】:

这个问题我迟到了将近一年。但万一有人发现自己处于与 Matěj Zábský 类似的位置,问问自己:

你能用Dictionary&lt;Tuple&lt;Type1, Type2, Type3&gt;, List&lt;Type4&gt;&gt;代替吗?

使用起来相当容易,并且考虑到哈希表(即字典)是 O(1) 数据结构,具有相当大的常量组件(如果您使用 ConcurrentDictionary 更是如此)它可能会执行得更快也。它还会使用更少的内存,并且转换为ConcurrentDictionary 非常简单。

当然,如果您需要为给定的Type1 键枚举所有给定的Type2,则嵌套字典可能是要走的路。但这是一个要求吗?

【讨论】:

  • 我绝对同意带有元组键的字典比嵌套字典更好,但我发现我的解决方案的嵌套性质很有用(我可以通过删除一个字典来删除所有带有 L1 键 X 的项目 - O( 1)而不是O(N),通过删除一个L2字典,所有具有L1和L2键组合的项目......)。然而,这可能并不经常发生,当然。 +1
【解决方案2】:

并发集合将防止数据损坏和崩溃,但代码在语义上不会与您当前的代码等效。例如,如果您迭代其中一个并发字典,some of the items may belong to different updates

从返回的枚举器 字典可以安全地同时使用 与读取和写入 字典,但它没有 代表一个瞬间的快照 词典。暴露的内容 通过枚举器可能包含 对字典的修改 在调用 GetEnumerator 之后。

如果您想保持您现在的确切行为,同时节省锁定成本,您可能希望使用ReaderWriterLockSlim 锁定,这特别适合读取多于写入的情况。

【讨论】:

  • 我认为ReaderWriterLockSlim 的开销比较大,因此对于许多快速操作来说通常不是最优的,即使其中大部分是读取操作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多