luy*_*619 5 memory concurrency atomic go
我知道可以发生g打印2然后给出以下代码0.
var a, b uint32
func f() {
a = 1
b = 2
}
func g() {
fmt.Println(b)
fmt.Println(a)
}
func main() {
go f()
g()
}
Run Code Online (Sandbox Code Playgroud)
如果我将所有读写更改为原子操作怎么办?是否保证如果g先打印2,那么还会打印1?
var a, b uint32
func f() {
atomic.StoreUint32(&a, 1)
atomic.StoreUint32(&b, 2)
}
func g() {
fmt.Println(atomic.LoadUint32(&b))
fmt.Println(atomic.LoadUint32(&a))
}
func main() {
go f()
g()
}
Run Code Online (Sandbox Code Playgroud)
不会。没有同步,因此不存在“发生在之前”的关系。
Goroutine 之间的同步是通过通道通信和锁定操作来完成的。
内存模型中的一个关键段落是:
在单个 goroutine 中,读取和写入的行为必须就像按照程序指定的顺序执行一样。也就是说,只有当重新排序不会改变语言规范定义的 Goroutine 内的行为时,编译器和处理器才可以对单个 Goroutine 内执行的读取和写入进行重新排序。由于这种重新排序,一个 Goroutine 观察到的执行顺序可能与另一个 Goroutine 观察到的顺序不同。例如,如果一个 goroutine 执行 a = 1; b = 2;,另一个人可能会在 a 的更新值之前观察到 b 的更新值。