在 c# 中 Parallel.ForEach 中的 r/w 字典条目是否安全

Is it safe to r/w dictionary entries in a Parallel.ForEach in c#

我有一个字典,我想在 foreach 循环中修改它的值,但是,由于我的应用程序时间紧迫,我试图避免所有不必要的锁定开销。

var loopData = new Dictionary<int, List<string>>();
var results = new Dictionary<int, List<string>>();

/// loopData and results are both initialized
/// with same set of keys.

Parallel.ForEach(loopData, data =>
    {
        var list = data.Value;
        /// manipulate list here

        /// Is this safe?
        results[data.Key] = list;
    });

标记的命令安全吗?即,read/write 到字典的不同键值对而不锁定。

注 1: 我知道并发集合命名空间及其所有宏伟的集合。我也知道我可以简单地 lock 突出显示的命令来确保它的安全。如前所述,我的目标是尽可能避免 不必要的 开销。

注2:问了一个类似的问题at this link。在那个问题中,容器的项目在 Parallel.ForEach 循环内被修改。然而,这里我们没有修改键值对,因此容器是完整的,只是指向的数据发生了变化。这使得它与上述问题不同。

更新

  1. 这段代码在没有锁定的情况下工作正常,但我必须确定。
  2. 尽管 ConcurrentDictionary 会增加尽可能少的开销,但如果这是安全的,我想避免它。

并发地从字典中读取是安全的,但并发地写入它或在并发地写入的同时读取它是不安全的。 ConcurrentDictionary 将是您并发插入的最快选择。

根据评论,我猜您很难理解您需要多少个并发词典。我在代码中的注释可能会有所帮助:

Parallel.ForEach(loopData, data =>
{
    var list = data.Value;       //<-- this is safe, because a read operation
    /// manipulate list here       <-- this is safe, because it operates on individual objects

    /// Is this safe?              <-- no, this is a write access
    results[data.Key] = list;
});

所以你只需要一个并发字典,那就是 results 变量。