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.
可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
回答1:
That is because for most environments, incrementing a memory location is not an atomic operation.
The sequence of events would be something like
- The compiler places the value 0 at the memory address 0xABCD
- Thread 1 reads 0xABCD into a register and increments the register value
- Thread 1 is interrupted by Thread 2
- Thread 2 reads the value 0 from the memory address 0xABCD into a register
- Thread 2 increments the value in the register
- Thread 2 writes the value from the register to 0xABCD
- Thread 2 reads the value 1 from 0xABCD, increments the register, and writes back again
- Thread 1 resumes
- Thread 1 writes the value from its register, 1, to 0xABCD, overwriting the value 2 that Thread 2 had previously written there.
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++;
}
Alternatively, in the .NET environment, one could use Interlocked.Increment
http://msdn.microsoft.com/en-us/library/dd78zt0c.aspx
Other environments have similar constructs.
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/