在 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
循环内被修改。然而,这里我们没有修改键值对,因此容器是完整的,只是指向的数据发生了变化。这使得它与上述问题不同。
更新
- 这段代码在没有锁定的情况下工作正常,但我必须确定。
- 尽管
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
变量。
我有一个字典,我想在 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
循环内被修改。然而,这里我们没有修改键值对,因此容器是完整的,只是指向的数据发生了变化。这使得它与上述问题不同。
更新
- 这段代码在没有锁定的情况下工作正常,但我必须确定。
- 尽管
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
变量。