Parallel.ForEach 中的竞争条件?
Race condition in Parallel.ForEach?
下面的代码中是否存在竞争条件?
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);
});
}
是的。
(已编辑以删除不正确和分散注意力的信息)
正如其他答案所说,您可以这样做:(此答案的其余部分早于我的更正(感谢 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));
});
}
而且显然没有覆盖对象或内存的风险。
是的,可能存在竞争条件。两个线程可能会在循环体中交错执行以下语句:
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));
下面的代码中是否存在竞争条件?
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);
});
}
是的。
(已编辑以删除不正确和分散注意力的信息)
正如其他答案所说,您可以这样做:(此答案的其余部分早于我的更正(感谢 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));
});
}
而且显然没有覆盖对象或内存的风险。
是的,可能存在竞争条件。两个线程可能会在循环体中交错执行以下语句:
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));