0

如果我有一个全局计数器,并且我有两个线程,每个线程在循环中将其递增 100 次,为什么我可以有一个不是 200 的值?我不明白如何访问变量是非原子的。

4

1 回答 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 环境中的线程的最佳参考(但无论您的环境如何,它都是有用的读物​​)如下

http://www.albahari.com/threading/

于 2012-09-25T21:12:33.960 回答