我想问一下c#中的队列如果ConcurrentQueue是安全线程,为什么这段代码的结果是~98 k?我有什么不对吗?
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这就是问题:
sum += result;
Run Code Online (Sandbox Code Playgroud)
那不是原子的.这是有效的:
var tmp = sum;
tmp += result;
sum = tmp;
Run Code Online (Sandbox Code Playgroud)
如果你的两个线程同时到达中间线,你认为会发生什么?
你可以解决这个问题Interlocked.Add:
while (queue.TryDequeue(out result))
{
Interlocked.Add(ref sum, result);
}
Run Code Online (Sandbox Code Playgroud)
请注意,这与使用无关ConcurrentQueue- 如果您的循环刚刚出现,您会看到同样的事情:
for (int i = 0; i < 50000; i++)
{
sum++; // Just as bad...
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
150 次 |
| 最近记录: |