atomic包中的 Swap、Load、Store 没有锁指令,是如何保证原子性呢?

来源:1-14 Go 并发编程最佳实践

慕丝1411558

2021-06-16 14:45:09

atomic 包中大概有5类方法集, Swap、Load、Store、Add、CAS。一直不理解 load、store 已经是最基本的行为了,怎么还能继续保证原子性呢?

然后我写了个case,使用 go tool compile 查看汇编,在 Swap、Load、Store 中也没有简单 lock 关键字的指令,这个该如何理解呢?

var a int32
var b int32

func main() {
	// MOVL    $1, AX
	// LEAQ    "".a(SB), CX
	// XCHGL   AX, (CX)
	// MOVL    AX, "".b(SB)
	b = atomic.SwapInt32(&a, 1)
	// MOVL    "".a(SB), AX
	// MOVL    AX, "".b(SB)
	// MOVL    $1, "".a(SB)
	b, a = a, 1

	// MOVL    "".a(SB), CX
	// MOVL    CX, "".b(SB)
	b = atomic.LoadInt32(&a)
	// MOVL    "".a(SB), CX
	// MOVL    CX, "".b(SB)
	b = a

	// MOVL    $1, CX
	// LEAQ    "".a(SB), DX
	// XCHGL   CX, (DX)
	atomic.StoreInt32(&a, 1)
	// MOVL    $1, "".a(SB)
	a = 1

	// MOVL    $1, CX
	// LEAQ    "".a(SB), DX
	// LOCK
	// XADDL   CX, (DX)
	atomic.AddInt32(&a, 1)
	// INCL    "".a(SB)
	a += 1
}

写回答

1回答

Xargin

2021-06-16

单个的读写行为并不一定是原子的,只是在 x86 平台上可能是(内存如果没有对齐,可能依然非原子)


同一个原子操作在不同平台可能实现有差别,

比如 x86 平台,内存对齐了,64 位变量读写就是原子的,但在 arm 之类的平台上可能就不是(这里我不确定哦),

读写这种单步操作的原子性是用 mesi 协议保证的,但 cas,add 这种 read-modify-write 多步的操作用 mesi 协议不能保证原子,必须要加 lock 前缀,

https://stackoverflow.com/questions/55995722/why-can-the-mesi-protocol-not-guarantee-atomicity-of-cmpxchg-on-x86-without-the


https://stackoverflow.com/questions/11065675/lock-prefix-of-intel-instruction-what-is-the-point



对于编程语言这种要跨平台的,同一个指令,

如 atomic.Cas 在不同的平台最终出来的汇编代码应该也是不一样的

0

Go高级工程师实战营

慕课网与 GoCN 社区官方联手打造,定义行业Go高级人才培养标准,4个月,快速晋升为P6+/D7级高级人才。

458 学习 · 266 问题

查看课程