ConcurrentQueue c#, inexact result?

I would like to ask about queue in c# If ConcurrentQueue is safe thread, why the result of this code is ~98 k? Do I something wrong?

class Program
{
    static int sum = 0;
    static ConcurrentQueue<int> queue = new ConcurrentQueue<int>();

    static void Main()
    {
        for (int i = 0; i < 100000; i++)
        {
            queue.Enqueue(1);
        }

        Task t1 = Task.Run(() => Calculate());
        Task t2 = Task.Run(() => Calculate());

        Task.WaitAll(t1, t2);

        Console.WriteLine($"Sum = {sum}");
        Console.ReadKey();
    }

    static void Calculate()
    {

        int result;
        while (queue.TryDequeue(out result))
        {
            sum += result;
        }
    }
}
Jon Skeet
people
quotationmark

This is the problem:

sum += result;

That's not atomic. It's effectively:

var tmp = sum;
tmp += result;
sum = tmp;

What do you think will happen if both of your threads reach the middle line at the same time?

You can fix this with Interlocked.Add:

while (queue.TryDequeue(out result))
{
    Interlocked.Add(ref sum, result);
}

Note that this has nothing to do with using ConcurrentQueue - you'd see the same thing if your loop had just been:

for (int i = 0; i < 50000; i++)
{
    sum++; // Just as bad...
}

people

See more on this question at Stackoverflow