这是多线程方法中Dictionary的安全使用吗?

时间:2015-07-07 14:12:43

标签: c# multithreading dictionary collections parallel-processing

我有一组项目(SortedPoints),我使用Parallel.ForEach迭代。每个项目都将成为名为Stripes的词典中的键。计算每个项目的价值是昂贵的,并且在BulidStripes方法中。

Parallel.ForEach(SortedPoints, point =>
    Stripes[point] = BuildStripes(point, pointToPosition)
); 

我可以将Stripes设为ConcurrentDictionary,但我想知道这是否有效:

1)使条纹成为常规字典。

2)连续迭代所有点并用条带填充Stripes到空对象。

3)并行迭代所有点并将Stripes中的映射替换为BuildStripes返回的实际值。

foreach(var point in SortedPoints)
    Stripes[point] = emptyStripe;
Parallel.ForEach(SortedPoints, point =>
    Stripes[point] = BuildStripes(point, pointToPosition)
);

如果每个线程都在一组单独的键上工作,并且每个键按照我的概述按顺序预先加载到Dictionary中,那么是设置键线程安全的值吗?我查看了Dictionary的源代码,它看起来很安全,但是这些集合是微妙的动物,很难发现并行错误。

创建字典后,我再也不会修改它,所有访问都是读取。

1 个答案:

答案 0 :(得分:1)

让我们看看事实。如果出现以下情况,可能会发生线程错误:

  • 添加新项目?都能跟得上
  • 在添加项目时调整字典大小。这不是问题,你的字典有固定的大小。
  • 两个线程尝试设置相同键的值。不会发生,因为您的SortedPoints集合具有不同的项目(是吗?)

还有其他选择吗?我没有看到一个。我认为你可以放心使用这种方法。

但是当然只是使用常规的ConcurrentDictionnary来获取可读性!也许你可以获得一些性能,但除非你对它进行基准测试,否则没有理由不使用ConcurrentDictionary。

Some docs about what ConcurrentDictionary deal with.