【发布时间】:2017-01-05 15:35:23
【问题描述】:
我有一个Dictionary<string, List<MyObject>>,我需要在List<MyObject> 上运行一些资源密集型操作。我试图弄清楚是否可以让 Dictionary 的每个键都有一个线程来执行资源密集型任务,以便每个线程都更新其键的列表。也就是说,多个线程同时更新字典中的不同项目?
请考虑以下简化伪代码 -
public void MyMethod() {
//The myDict object needs to be shared by all threads.
Dictionary<string, List<MyObject>> myDict = new Dictionary<string, List<MyObject>>();
//GetKeyValue() may return the same key multiple times
foreach(var kv in GetKeyValue()) {
if(myDict.ContainsKey(kv.Key) { myDict[kv.Key].Add(kv.Value); }
else { myDict.Add(kv.Key, kv.Value); }
Task.Factory.StartNew(() => { RunSubsetSum(kv.Key, myDict); });
}
}
//Resource intensive method
public void RunSubsetSum(string key, Dictionary<string, List<MyObject>> myDict) {
//Lock on key so that no two threads run for the same key
lock(key){
foreach(var valueToRemove in GetRemovableObjs())
myDict[kv.Key].Remove(valueToRemove);
}
}
基本上,这个想法是-
- 没有两个线程同时为同一个键运行 - lock(key) 会使它们排队(按顺序运行)吗?
- 所有正在运行的线程都可以独立更新同一个字典 - 我希望多个线程能够同时更新同一个字典中的不同项目。
我尝试了上述方法,但结果似乎不一致。我认为这是因为 MyMethod() 更新了 RunSubsetSum() 已经在运行的键的字典,但不确定如何在不中断其他键循环的情况下锁定 MyMethod() 中的键。我想知道 C# 是否为这个问题提供了更简单的解决方案。有什么想法吗?
注意:我正在考虑创建一个字典,以便我可以跟踪当前正在处理哪些键并更新 MyMethod() 以缓冲键直到线程完成,但如果可以的话,我想避免添加它避免逻辑过于复杂。
【问题讨论】:
-
你为什么不使用
ConcurrentDictionary? -
@TimSchmelter 他不需要一个(字典只能从一个线程访问),这并不能解决他遇到的问题(字典中的值被多个线程访问) )。
-
@Servy:当然,他的想法是为字典中的每个键设置一个线程。但我的建议是使用
ConcurrentDictionary来避免这种情况。如果他访问列表,他需要锁定它 -
再一次,字典首先不需要从多个线程访问,单个线程管理字典并提取然后由多个线程使用的值,所以没有必要对于
ConcurrentDictionary,最重要的是,使用一个并不能解决不同线程访问多个值的问题。 -
抱歉,伪代码没有反映出来,但字典对象应该由所有线程共享。不同线程使用同一个字典并可能同时且独立地更新自己的键的想法。
标签: c# multithreading