Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Race condition in Parallel.ForEach?

Is there a possible race condition in below code?

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);
    });
}  
like image 378
Vikas Avatar asked Dec 14 '22 07:12

Vikas


1 Answers

Yes, there is a possible race condition. Two threads might interleave the statements in the loop body as follows:

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

Because objData is declared outside the loop, the two threads share the same variable. As a result, Thread #2 overwrites the objData reference set by Thread #1, and Thread #2's objData gets added to cbOutput twice.

To prevent objData from being shared by multiple threads, make it a local variable:

SomeDataOutput objData = GetOutputData(objInput);
cbOutput.Add(objData);

Or you can get rid of the variable altogether:

cbOutput.Add(GetOutputData(objInput));
like image 69
Michael Liu Avatar answered Dec 27 '22 22:12

Michael Liu