【发布时间】:2023-04-03 12:51:02
【问题描述】:
我在 C# 6.0 and the .NET 4.6 framework 一书中读到了这一点:
“赋值和简单的算术运算不是原子的”。
那么,它到底是什么意思?
【问题讨论】:
-
看看here
-
转到stackoverflow.com/questions/11745440/…这里是您问题的完整定义。
标签: c#
我在 C# 6.0 and the .NET 4.6 framework 一书中读到了这一点:
“赋值和简单的算术运算不是原子的”。
那么,它到底是什么意思?
【问题讨论】:
标签: c#
原子操作是不能在中途中断的操作,例如线程。以语句为例
_value++;
如果你有两个线程同时执行这段代码,起始值为0,你可能会有以下情况
_value, 0_value, 0_value, 1_value, 1所以现在,即使我们调用了两次增量,_value 中的最终值是1,而不是预期的2。这是因为自增运算符不是原子的。
函数Interlocked.Increment,然而,是原子的,所以将上面的代码替换为
Interlocked.Increment(ref _value);
将解决给定的竞争条件。
编辑:作为词源学的一点,“原子”通常意味着“不可分割”——我们熟悉的化学术语是一个误称原子是不可分割的,只是为了后来的发现将它们进一步分解为亚原子、夸克和量子水平。
【讨论】:
原子是不可分割的。原子操作是“不可分割”的操作,不能分割,例如中断。
微处理器不是按顺序执行的,也就是说,一条指令接一条指令,就像写在程序中一样。有外部对象,可以改变执行流程。中断就是一个很好的例子。
所以,您可能知道MOV 指令,它几乎适用于所有处理器。
想象一下它是由 CPU 执行的。一个 32 位的值被移动到一个 32 位的寄存器中。
现在,在移动了 16 位之后,就会发生中断请求。
MOV 指令不会停止,而是会执行到最后,然后 CPU 将处理中断MOV 指令将立即停止并执行中断。问题是,如果中断访问了MOV写入的寄存器,内容不清楚,因为MOV操作只完成了一半!现在,在普通处理器上,MOVs 在处理器字长上运行是原子的。如果处理器字为 16 位宽,则 16 位 MOV 指令将是原子的。
但是,32 位 MOV 操作不会是原子的。这种非原子的MOV 指令通常不是由指令集提供,而是由一些高级语言提供,例如C 的long long 或C# 的long。对这些数据类型的操作不保证是原子的!
【讨论】: