如果我有一个全局计数器,并且我有两个线程,每个线程在循环中将其递增 100 次,为什么我可以有一个不是 200 的值?我不明白如何访问变量是非原子的。
问问题
805 次
1 回答
2
这是因为对于大多数环境,增加内存位置并不是原子操作。
事件的顺序将类似于
- 编译器将值 0 放在内存地址 0xABCD
- 线程 1 将 0xABCD 读入寄存器并递增寄存器值
- 线程 1 被线程 2 中断
- 线程 2 从内存地址 0xABCD 读取值 0 到寄存器中
- 线程 2 递增寄存器中的值
- 线程 2 将寄存器中的值写入 0xABCD
- 线程 2 从 0xABCD 读取值 1,递增寄存器,然后再次写回
- 线程 1 恢复
- 线程 1 将其寄存器 1 中的值写入 0xABCD,覆盖线程 2 之前写入的值 2。
为确保结果一致,您必须使增量操作具有原子性。这通常通过在增量操作周围放置一个线程锁来完成。例如,在 C# 中可能看起来像
object mylock = new object();
...
lock (mylock)
{
myInt++;
}
或者,在 .NET 环境中,可以使用 Interlocked.Increment
http://msdn.microsoft.com/en-us/library/dd78zt0c.aspx
其他环境也有类似的结构。
我遇到过的关于 .NET 环境中的线程的最佳参考(但无论您的环境如何,它都是有用的读物)如下
于 2012-09-25T21:12:33.960 回答