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

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


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

1)使Stripes成为常规词典。

2)依次遍历所有点,并在Stripes中填充到空对象的映射。

3)并行遍历所有点,并将Stripe中的映射替换为BuildStripes返回的实际值。

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


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

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

最佳答案

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


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


还有其他选择吗?我没看到。我认为使用此方法是安全的。

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

Some docs about what ConcurrentDictionary deal with.

08-27 00:32