【问题标题】:Does my use of Dictionary require locking?我对 Dictionary 的使用是否需要锁定?
【发布时间】:2012-06-17 15:09:57
【问题描述】:

许多线程都可以访问summary。每个线程都有一个唯一的键来访问字典;

Dictionary<string, List<Result>> summary;

以下操作是否需要锁定?

  1. summary[key] = new List&lt;Result&gt;()
  2. summary[key].Add(new Result());

似乎我不需要锁定,因为每个线程都会使用不同的键访问字典,但 (1) 不会因为同时向字典中添加新记录而与其他线程一起出现问题?

【问题讨论】:

  • 要么可以修改整个字典(即,它用于保存数据的任何数据结构),因此需要锁定。例如,在哈希表中,键可能会发生冲突;在树中,两者都可能尝试旋转相同的子树。 IOW,是的,除非有问题的字典特别支持并发访问,否则您需要锁定。
  • @Jerry,您的“评论”与答案有何区别?
  • @KirkWoll:我不确定 .NET 如何定义其 Dictionary 类。此外,它足够短,可以放在评论中。 :-)

标签: c# multithreading dictionary locking


【解决方案1】:

是的,您需要使用锁定。

字典对于添加操作不是线程安全的。 如果您使用的是 .NET 4,则可以考虑切换到 ConcurrentDictionary。否则,您应该创建自己的线程安全集合(例如this)。

考虑使用ReaderWriterLockSlim 同步访问您的集合(以防您不使用 ConcurrentDictionary)。

【讨论】:

  • +1, ReaderWriterLockSlim 效果很好,也可以在 .NET 3.5 中找到。
  • @the coon,对不起,但我忘了问:我现在使用ConcurrentDictionary&lt;string, List&lt;Result&gt;&gt;,但我是否还需要将List&lt;Result&gt; 替换为BlockingColleciton&lt;Result&gt; 并使用ConcurrentDictionary&lt;string, BlockingColleciton&lt;Result&gt;&gt;
  • 不,如果您不在应用程序的其他位置保留对列表的引用。如果您通过字典读取/写入列表(例如 dict[key].Add(someValue),那么它是安全的,因为字典将确保线程安全地访问列表。
  • @the coon,你的意思是如果我这样使用它:var list = new List&lt;Result&gt;; var dic = new ConcurrentDictionary&lt;string, List&lt;Result&gt;&gt;(); dic[key] = list;,那么我确实需要BlockingColleciton&lt;Result&gt;而不是List&lt;Result&gt;,对吧?
  • 您可以直接执行 dic[key] = new List() 并且您不需要锁定列表。所以你可以继续使用 List.
【解决方案2】:

对您的字典的所有写访问必须被锁定。不能保证访问不同的键是线程安全的,事实上,它不是。

来自MSDN

只要不修改集合,字典可以同时支持多个阅读器。即便如此,通过集合枚举本质上不是线程安全的过程。在枚举与写访问竞争的极少数情况下,必须在整个枚举期间锁定集合。要允许集合被多个线程访问以进行读写,您必须实现自己的同步。

【讨论】:

    【解决方案3】:

    默认情况下,字典不是线程安全的。你要添加什么并不重要。最重要的是:您无法控制来自不同线程的并发添加。所以你肯定需要锁。或者切换到线程安全集合(即 .NET 4+ 的 CocnurrentDictionary)

    【讨论】:

      猜你喜欢
      • 2021-09-28
      • 2020-11-29
      • 1970-01-01
      • 2015-10-31
      • 1970-01-01
      • 2011-12-01
      • 2011-02-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多