并发字典安全使用
Concurrent Dictionary safety usage
我需要线程安全的方式来获取 ConcurrentDictionary(string, List) 的每个项目
使用以下结构安全吗?
foreach (var item in concurrentDict)
{
var readonlyCollection = item.Value.AsReadOnly();
//use readonly collection, (I need only Values of the concurrent dictionary)
}
我想使用字典安全值。
foreach
部分很好,但需要注意的是,同时添加的项目可能会或可能不会包含在迭代中。不过你不会得到例外。
但是,您需要小心使用类型为 List
的 item.Value
,因为列表不是线程安全的。如果在循环中读取列表时另一个线程修改了列表,则可能会出现异常。
在您的列表上调用 AsReadOnly()
没有帮助,因为您得到的是原始列表的包装器。如果从包装器内的原始列表中读取会抛出异常,那么从包装器中读取也会抛出异常。此外,您不能简单地通过对嵌套列表进行浅表复制来解决此问题,因为在复制时可能会执行并发修改。
一种方法是在读写列表时lock
列表:
foreach (var item in concurrentDict) {
List<string> listCopy;
lock (item.Value) {
listCopy = item.Value.ToList();
}
//use collection copy
}
当一个写线程改变字典里面的列表时,它需要执行相同的锁定:
if (concurrentDict.TryGetValue("mykey", var out list)) {
lock (list) {
list.Add("newValue");
}
}
我需要线程安全的方式来获取 ConcurrentDictionary(string, List) 的每个项目
使用以下结构安全吗?
foreach (var item in concurrentDict)
{
var readonlyCollection = item.Value.AsReadOnly();
//use readonly collection, (I need only Values of the concurrent dictionary)
}
我想使用字典安全值。
foreach
部分很好,但需要注意的是,同时添加的项目可能会或可能不会包含在迭代中。不过你不会得到例外。
但是,您需要小心使用类型为 List
的 item.Value
,因为列表不是线程安全的。如果在循环中读取列表时另一个线程修改了列表,则可能会出现异常。
在您的列表上调用 AsReadOnly()
没有帮助,因为您得到的是原始列表的包装器。如果从包装器内的原始列表中读取会抛出异常,那么从包装器中读取也会抛出异常。此外,您不能简单地通过对嵌套列表进行浅表复制来解决此问题,因为在复制时可能会执行并发修改。
一种方法是在读写列表时lock
列表:
foreach (var item in concurrentDict) {
List<string> listCopy;
lock (item.Value) {
listCopy = item.Value.ToList();
}
//use collection copy
}
当一个写线程改变字典里面的列表时,它需要执行相同的锁定:
if (concurrentDict.TryGetValue("mykey", var out list)) {
lock (list) {
list.Add("newValue");
}
}