问题描述
如果我有一个全局计数器并且我有两个线程,每个线程都在循环中将其递增 100 次,为什么我可以使用 200 以外的值?我不明白如何访问变量是非原子的.
If I have a global counter and I have two threads that are each incrementing it 100 times in a loop, why is it possible that I can have a value other than 200? I don't see how accessing the variable is nonatomic.
推荐答案
那是因为对于大多数环境,增加内存位置不是原子操作.
That is because for most environments, incrementing a memory location is not an atomic operation.
事件的顺序类似于
- 编译器将值 0 放在内存地址 0xABCD 处
- 线程 1 将 0xABCD 读入寄存器并递增寄存器值
- 线程 1 被线程 2 中断
- 线程 2 从内存地址 0xABCD 读取值 0 到寄存器中
- 线程 2 递增寄存器中的值
- 线程 2 将寄存器中的值写入 0xABCD
- 线程 2 从 0xABCD 读取值 1,增加寄存器,然后再次写回
- 线程 1 恢复
- 线程 1 将其寄存器 1 中的值写入 0xABCD,覆盖线程 2 先前写入的值 2.
为了确保一致的结果,您必须使增量操作具有原子性.这通常通过在增量操作周围放置线程锁来完成.例如,在 C# 中可能看起来像
To ensure a consistent result, you must make the increment operation atomic. This is often done by placing a thread lock around the increment operation. For example, in C# that might look like
object mylock = new object();
...
lock (mylock)
{
myInt++;
}
或者,在 .NET 环境中,可以使用 Interlocked.Increment
Alternatively, in the .NET environment, one could use Interlocked.Increment
http://msdn.microsoft.com/en-us/library/dd78zt0c.aspx
其他环境也有类似的结构.
Other environments have similar constructs.
我在 .NET 环境中遇到的关于线程的最佳参考(但无论您的环境如何都是有用的阅读)如下
The best reference I have ever come across for threading in the .NET environment (but is a useful read no matter what your environment) is the following
http://www.albahari.com/threading/
这篇关于全局变量和线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!