以下代码中是否存在竞争条件?
public void Process(List<SomeObject> list)
{
SomeDataOutput objData=null;
ConcurrentBag<SomeDataOutput> cbOutput = new ConcurrentBag<SomeDataOutput>();
ParallelOptions po = new ParallelOptions(){MaxDegreeOfParallelism=4};
Parallel.ForEach(list, po, (objInput) =>
{
objData = GetOutputData(objInput);//THIS LINE IS THE ONE I AM UNSURE OF. CAN objData GET OVERWRITTEN BY MULTIPLE PARALLEL THREADS?
cbOutput.Add(objData);
});
}
答案 0 :(得分:11)
是的,可能存在竞争条件。两个线程可能会在循环体中交错语句,如下所示:
Thread #1 Thread #2
================================== ==================================
objData = GetOutputData(objInput);
objData = GetOutputData(objInput);
cbOutput.Add(objData);
cbOutput.Add(objData);
因为objData
在循环外声明,所以两个线程共享同一个变量。因此,线程#2会覆盖线程#1设置的objData
引用,线程#2的objData
会被添加到cbOutput
两次。
为防止多个线程共享objData
,请将其设为局部变量:
SomeDataOutput objData = GetOutputData(objInput);
cbOutput.Add(objData);
或者你可以完全摆脱变量:
cbOutput.Add(GetOutputData(objInput));
答案 1 :(得分:1)
是
(编辑删除错误且分散注意力的信息)
正如另一个答案所说,你可以这样做:(这个答案的剩余部分早于我的更正(感谢Ben Voight))。
public void Process(List<SomeObject> list)
{
ConcurrentBag<SomeDataOutput> cbOutput = new ConcurrentBag<SomeDataOutput>();
ParallelOptions po = new ParallelOptions(){MaxDegreeOfParallelism=4};
Parallel.ForEach(list, po, (objInput) =>
{
cbOutput.Add(GetOutputData(objInput));
});
}
显然没有覆盖物体或记忆的风险。