在同一个 Goroutine 中,如果我们有下面的语句:

a = 1
b = 3
b = 3a = 1

那这会造成什么问题呢?比如我们可以看一下下面这些有问题的代码:

var a, b int

func f() {
    a = 1
    b = 2
}
func main() {
    go f()
    print(a)
    print(b)
}

打印出来的 a 和 b 的值可能是赋值之后的,也可能是 0

再来看另一个有问题的代码:

var a string
var done bool

func setup() {
    a = "hello, world"
    done = true
}

func main() {
    go setup()
    for !done {}
    print(a)
}
setupfor !done {}
setup

因此,Go内存模型其实是一个概念,指定了某些条件,在这些条件下,可以保证在一个Goroutine中对一个共享变量的写入,可以被另一个Goroutine观察到。

什么是 Happens Before

a = 1; b = 3
a = 1b = 3a = 1b = 3a = 1b = 3

如果对一个变量的赋值操作w要保证被另一个读取操作r观察到,运用 Happens before 概念,我们可以得出需要满足如下条件:

  • w happens before r
  • 任何其他对变量的赋值操作要么happens before w,要么happens after r

下面介绍一些在Go编程中可以确定是 happens before 的语句(不全,更详细的可以参考官方文档)

init()

package apackage bpackage binit()package ainit()

channel

close()
sync.Mutex()

推荐阅读

关于 Golang Memory Model,就推荐一篇文章,官方文章,讲的很清楚