在C#中,"原子"是什么意思?

msh*_*hwf 4 c#

我在C#6.0和.NET 4.6框架中读到了这个:

"赋值和简单算术运算不是原子的".

那么,它究竟意味着什么?

Dav*_*vid 15

原子操作是不能在中途中断的操作,例如通过线程.以该声明为例

_value++;
Run Code Online (Sandbox Code Playgroud)

如果您有两个线程一次执行此代码且起始值为0,则可能具有以下内容

  • 线程A读取_value,0
  • 线程A加1,1
  • 线程B读取_value,0
  • 线程B加1,1
  • 线程A分配给_value,1
  • 线程B分配给_value,1

所以现在,即使我们被称为增量的两倍,最终的价值_value1,不是预期的2.这是因为增量运算符不是原子的.

Interlocked.Increment但是,该函数原子函数,因此用上面的代码替换

Interlocked.Increment(ref _value);
Run Code Online (Sandbox Code Playgroud)

会解决给定的竞争条件.


cad*_*luk 7

原子是不可分割的.原子操作是"不可分割的"操作,不能被分割,例如中断.

微处理器不按顺序执行,即指令后的指令,就像在程序中写入一样.有外部对象,可以改变执行流程.一个很好的例子是中断.

因此,您可能知道该MOV指令,该指令几乎可用于所有处理器.
想象一下,它是由CPU执行的.将32位值移入32位寄存器.
现在,在移动16位后,发生中断请求.

  • 原子MOV指令不会停止但会执行到最后,然后 CPU将处理中断
  • 一个MOV指令不是原子将立即停止执行中断.问题是,如果中断访问的寄存器,这是由写入MOV,内容还不清楚,因为MOV操作仅完成一半!

现在,在通常的处理器上,MOV对处理器的字大小进行操作是原子的.如果处理器字是16位宽,则16位MOV指令将是原子的.
但是,32位MOV操作不是原子操作.这种非原子MOV指令通常不是由指令集提供的,而是由一些高级语言提供的,如C long long或C#long.对这些数据类型的操作保证是原子的!