在 golang 中,有原子包,能够实现原子操作,在我分析和猜想下,感觉解开了谜团
具体用法不说了,网上一大堆什么 cas,add,load,store 等,主要是底层实现
arm 架构
在 amd 架构下,通过汇编指令加锁来实现
代码在src/runtime/internal/atomic/atomic_amd64.s
// uint64 Xadd64(uint64 volatile *val, int64 delta)
// Atomically:
// *val += delta;
// return *val;
TEXT ·Xadd64(SB), NOSPLIT, $0-24
MOVQ ptr+0(FP), BX
MOVQ delta+8(FP), AX
MOVQ AX, CX
LOCK
XADDQ AX, 0(BX)
ADDQ CX, AX
MOVQ AX, ret+16(FP)
RET
可以看到在执行 XADDQ
命令之前,先进行 LOCK
加锁把内存地址锁住,然后执行下面的操作
amd 架构
在 arm 架构下,似乎没看到 LOCK
指令
src/runtime/internal/atomic/atomic_arm64.s
// uint64 Xadd64(uint64 volatile *ptr, int64 delta)
// Atomically:
// *val += delta;
// return *val;
TEXT ·Xadd64(SB), NOSPLIT, $0-24
MOVD ptr+0(FP), R0
MOVD delta+8(FP), R1
MOVBU internal∕cpu·ARM64+const_offsetARM64HasATOMICS(SB), R4
CBZ R4, load_store_loop
LDADDALD R1, (R0), R2
ADD R1, R2
MOVD R2, ret+16(FP)
RET
load_store_loop:
LDAXR (R0), R2
ADD R2, R1, R2
STLXR R2, (R0), R3
CBNZ R3, load_store_loop
MOVD R2, ret+16(FP)
RET
在 arm 架构下没有了 LOCK
指令,但是用到了 MOVBU internal∕cpu·ARM64+const_offsetARM64HasATOMICS(SB), R4
这个命令,虽然没查到怎么用,但是看变量命令,可以理解是将原子位置一个值再操作