对ConcurrentDictionary的线程安全更改
本文关键字:安全 线程 ConcurrentDictionary | 更新日期: 2023-09-27 18:08:15
我在Parallel.ForEach
循环中填充ConcurrentDictionary
:
var result = new ConcurrentDictionary<int, ItemCollection>();
Parallel.ForEach(allRoutes, route =>
{
// Some heavy operations
lock(result)
{
if (!result.ContainsKey(someKey))
{
result[someKey] = new ItemCollection();
}
result[someKey].Add(newItem);
}
}
如何在不使用lock语句的情况下以线程安全的方式执行最后的步骤?
EDIT:假设ItemCollection
是线程安全的
我认为你想要GetOrAdd
,它被明确地设计为要么获取一个现有的项目,要么添加一个新的,如果没有给定键的条目。
var collection = result.GetOrAdd(someKey, _ => new ItemCollection());
collection.Add(newItem);
如问题注释中所述,这假设ItemCollection
是线程安全的。
您需要使用GetOrAdd
方法。
var result = new ConcurrentDictionary<int, ItemCollection>();
int someKey = ...;
var newItem = ...;
ItemCollection collection = result.GetOrAdd(someKey, _ => new ItemCollection());
collection.Add(newItem);
假设ItemCollection.Add
不是线程安全的,您将需要一个锁,但是您可以减小临界区域的大小。
var collection = result.GetOrAdd(someKey, k => new ItemCollection());
lock(collection)
collection.Add(...);
更新:因为它似乎是线程安全的,你根本不需要锁
var collection = result.GetOrAdd(someKey, k => new ItemCollection());
collection.Add(...);