为什么x86的INC指令不是原子的?

pyt*_*nic 20 c assembly x86-64 atomic

我已经读过x86的INC指令不是原子的.我的问题是怎么来的?假设我们在x86-64上递增64位整数,我们可以用一条指令来完成,因为INC指令适用于内存变量和寄存器.那么为什么它不是原子的呢?

Kag*_*nar 18

为什么会这样?处理器内核仍然需要读取存储在存储器位置的值,计算它的增量,然后将其存储回来.读取和存储之间存在延迟,同时另一个操作可能会影响该存储器位置.

即使执行无序,处理器内核也"足够智能",不会跳过自己的指令,也不负责在时间间隔内修改此内存.但是,另一个核心可能已发出修改该位置的指令,DMA传输可能会影响该位置,或者其他硬件以某种方式触及该存储器位置.

  • 您应该更清楚"另一种操作"的含义.当然,在同一个cpu内核上不会发生其他操作,只能在其他内核/ cpu或其他硬件上摆弄内存总线. (2认同)

Fra*_*kH. 18

现代x86处理器作为其执行流程的一部分,将x86指令"编译"为较低级别的操作集; 英特尔称之为uOps,AMD rOps,但它归结为某些类型的单个x86指令由CPU中的实际功能单元执行为几个步骤.
这意味着,例如,:

INC EAX
Run Code Online (Sandbox Code Playgroud)

被作为单个"迷你操作"执​​行uOp.inc eax(让我称之为 - 他们没有暴露).
对于其他操作数,事物看起来会有所不同,例如:

INC DWORD PTR [ EAX ]
Run Code Online (Sandbox Code Playgroud)

低级分解虽然看起来更像:

uOp.load tmp_reg, [ EAX ]
uOp.inc tmp_reg
uOp.store [ EAX ], tmp_reg
Run Code Online (Sandbox Code Playgroud)

因此不是原子地执行的.另一方面,如果你在前缀中LOCK INC [ EAX ],那将告诉管道的"编译"阶段以不同的方式分解,以确保满足原子性要求.

其原因当然是其他人提到的 - 速度; 为什么要做一些原子的东西,如果不总是需要的话必然要慢

  • "mini-op"分解与原子性无关,因为单个cpu核心不能在指令中间中断.事实上,没有锁前缀的inc在单核机器上是完全原子的.只有当其他核心(或更加模糊,总线上的其他硬件)可以访问锁定前缀重要的内存时. (3认同)
  • @R ..:如果你说没有“锁”的非原子性对于重要的用例(同步原语)在单核机器上没有任何影响,那么我同意。但我不同意这使得“默认”原子性 - 你只是不需要单核上的_同步_原子性。 (2认同)