0

I made two functions like below

one is just adding int values with linq

private long GetSumList(List<long> numbers)
{
    return numbers.Sum();
}

the other one is adding int values with Parallel.Foreach

private long GetSumListWithParallel(List<long> numbers)
{
    long retv = 0;

    Parallel.ForEach(numbers, number =>
    {
        retv += number; // It returns different return whenever I execute it.
        //Interlocked.Add(ref retv, number); // It returns always the same value whenever I execute it.
    });

    return retv;
}

I thought I didn't need to care about race condition, when I just adding integer numbers. Just because I thought that adding numbers had nothing to do with the order in which they were executed. if there were subtraction or multiplication, I would have care about race condition.

Why does this function return always different values? And What is the thing I should care about making parallel code?

Masuri
  • 894
  • 2
  • 9
  • 19
  • Subtraction and multiplication also commute for integers. – see sharper Apr 09 '21 at 01:05
  • 2
    I don't believe `+=` is an atomic operation and so isn't thread-safe –  Apr 09 '21 at 01:06
  • 1
    If you want to speed up the summing of a list using `Parallel`, you could divide it into multiple parts (e.g. each thread owns 1/4 of the list), sum those parts individually, and then sum the resulting sums just before you return from the method. – ProgrammingLlama Apr 09 '21 at 01:32

1 Answers1

3

The problem is not mathematical, but to do with atomicity and thread safety. That is to say, integer addition is commutative mathematically (order does not count), but += is not atomic,

i.e., if two parallel thread do a += operation at the same time, then the result is unpredictable. That's exactly why Interlocked.Add exists.

see sharper
  • 11,505
  • 8
  • 46
  • 65