【问题标题】:Dictionary weird behavior when adding item in Parallel.For [duplicate]在Parallel.For中添加项目时的字典奇怪行为[重复]
【发布时间】:2018-12-04 15:56:38
【问题描述】:

当我尝试在 Parallel 循环中将项目添加到字典中时,我发现了一件有趣的事情。它会引发NullReferenceException 异常。我可以修复它,但我不知道它为什么会抛出该异常。我想知道是否有人可以帮助我澄清这一点。下面是源码,很简单。

class Program
{
    private static Dictionary<int, Projection> CachedProjections =
        new Dictionary<int, Projection>();

    static void Main(string[] args)
    {
        var key = 3857;
        Parallel.For(0, 400, _ => 
        {
            Projection projection = null; // If remove the null initialization it works well.
            if (CachedProjections.ContainsKey(key))
            {
                projection = CachedProjections[key];
            }
            else
            {
                projection = new Projection();
                CachedProjections[key] = projection;
            }
        });

        Console.Read();
    }
}

public class Projection
{
    public Projection()
    {
        Thread.Sleep(10); // If comment out this line, it works well too.
    }
}

【问题讨论】:

  • 如果您想在多线程中使用字典,请使用ConcurrentDictionary
  • 作为非静态方法试试
  • @FelixQuehl 应该完全相关

标签: c# .net dictionary task-parallel-library parallel.for


【解决方案1】:

字典对于写+(任何其他)不是线程安全的。这意味着您需要锁定所有字典操作,这可能会消除您想要实现的所有事情。您也可以查看并发字典,但不要假设它会更快 - 它...复杂并且取决于您是否有竞争读+读、读+写、写+写等等。

【讨论】:

  • A ConcurrentDictionary 比在所有操作中使用锁要快,而且非常容易使用。
  • @Rango 这是一个非常简单的陈述;它真的取决于竞争操作是什么
  • 我只是提到了你的简单陈述“但不要假设它会更快 - 它是......复杂” ConcurrentDictionary为每个使用单独的锁哈希桶因此应该优于需要对所有操作进行总锁定的普通字典。至少如果你像 OP 一样使用它(ContainsKey + indexer)
【解决方案2】:

因为Dictionary 不是线程安全的:

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

有关线程安全的替代方案,请参阅ConcurrentDictionary

【讨论】:

    【解决方案3】:

    Dictionary&lt;K, V&gt; 不是线程安全的。将Thread-Safe Collections 用于多线程应用程序。在您的情况下使用ConcurrentDictionary&lt;TKey,TValue&gt; Class

    另见:How to: Add and Remove Items from a ConcurrentDictionary

    【讨论】:

      猜你喜欢
      • 2014-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-14
      • 1970-01-01
      相关资源
      最近更新 更多