我在C#6.0和.NET 4.6框架中读到了这个:
“赋值和简单算术运算不是原子的”。
那么,它究竟意味着什么?
答案 0 :(得分:10)
原子操作是不能在中途中断的操作,例如通过线程。举个例如声明
_value++;
如果您有两个线程同时执行此代码且起始值为0
,则可能具有以下内容
_value
,0 _value
,0 _value
,1 _value
,1 所以现在,即使我们调整了两次增量,_value
中的最终值为1
,而不是预期的2
。这是因为增量运算符不原子。
函数Interlocked.Increment
,但是原子,所以用
Interlocked.Increment(ref _value);
将解决给定的竞争条件。
答案 1 :(得分:6)
原子是不可分割的。原子操作是不可分割的"操作,不能分割,例如中断。
微处理器不按顺序执行,即指令后指令,就像在程序中写入一样。有外部对象,可以改变执行流程。一个很好的例子是中断。
因此,您可能知道MOV
指令,该指令几乎适用于所有处理器
想象一下,它是由CPU执行的。将32位值移入32位寄存器
现在,在移动了16位之后,发生了中断请求。
MOV
指令不会停止但会执行到最后然后 CPU将处理中断MOV
指令将立即停止并执行中断。问题是,如果中断访问了由MOV
写入的寄存器,内容不清楚,因为MOV
操作只完成了一半!现在,在通常的处理器上,MOV
对处理器的字大小进行操作是原子的。如果处理器字是16位宽,则16位MOV
指令将是原子的
但是,32位MOV
操作不是原子操作。这种非原子MOV
指令通常不是由指令集提供的,而是由一些高级语言提供的,如C long long
或C#' long
。这些数据类型的操作不保证是原子的!