以下代码中是否存在可能的比赛条件?

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);
    });
}

最佳答案

是的,有一个可能的比赛条件。两个线程可以交错循环体中的语句,如下所示:

Thread #1                             Thread #2
==================================    ==================================
objData = GetOutputData(objInput);
                                      objData = GetOutputData(objInput);
cbOutput.Add(objData);
                                      cbOutput.Add(objData);

因为objData是在循环外部声明的,所以两个线程共享同一个变量。结果,thread 2重写thread 1设置的objData引用,thread 2的objData被添加到cbOutput两次。
要防止objData被多个线程共享,请将其设置为局部变量:
SomeDataOutput objData = GetOutputData(objInput);
cbOutput.Add(objData);

或者您可以完全去掉变量:
cbOutput.Add(GetOutputData(objInput));

07-28 08:44