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;
}
}
}
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...
}
See more on this question at Stackoverflow