C# 对ConcurrentDictionary的线程安全更改
我正在并行地填充C# 对ConcurrentDictionary的线程安全更改,c#,parallel-processing,task-parallel-library,parallel.foreach,concurrentdictionary,C#,Parallel Processing,Task Parallel Library,Parallel.foreach,Concurrentdictionary,我正在并行地填充ConcurrentDictionary。ForEach循环: var result = new ConcurrentDictionary<int, ItemCollection>(); Parallel.ForEach(allRoutes, route => { // Some heavy operations lock(result) { if (!result.ContainsKey(someKey))
ConcurrentDictionary
。ForEach循环:
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);
}
}
var result=新的ConcurrentDictionary();
Parallel.ForEach(所有路由,路由=>
{
//一些重大行动
锁定(结果)
{
如果(!result.ContainsKey(someKey))
{
结果[someKey]=新的ItemCollection();
}
结果[someKey]。添加(newItem);
}
}
如何在不使用lock语句的情况下以线程安全的方式执行最后的步骤
编辑:假设ItemCollection
是线程安全的。我认为您需要,它被明确设计为获取现有项,或者在给定键没有条目时添加新项
var collection = result.GetOrAdd(someKey, _ => new ItemCollection());
collection.Add(newItem);
如问题注释中所述,这假设ItemCollection
是线程安全的。您需要使用该方法
var result=新的ConcurrentDictionary();
int someKey=。。。;
var newItem=。。。;
ItemCollection=result.GetOrAdd(someKey,=>newitemcollection());
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(...);
是
ItemCollection.Add
线程安全吗?如果不是,你需要一个锁。@ken2k:除非我的情况有一个条件元素。如果密钥不存在,请创建一个新的ItemCollection
,否则在该密钥处向现有的ItemCollection
添加一个项目。@dcastro:是的,请假设ItemCollection是线程安全的。这可能不像看上去那么安全:@jeffdot:我认为在这种情况下这不是一个问题-在任何锁中都不需要调用ItemCollection
构造函数…你设想的是什么问题?因为有关于锁定的讨论,而且因为ConcurrentDictionary
确实有一个内部锁,我觉得我们是通过让人们认为GetOrAdd
和AddOrUpdate
是原子的或在字典的锁内调用,增加了风险。我注意到,您给出了公平的警告,即ItemCollection
必须是线程安全的。OP回复了您的评论,说ItemCollection是线程安全的。@JonSkeet谢谢,没有注意到。
var collection = result.GetOrAdd(someKey, k => new ItemCollection());
collection.Add(...);