在同一个 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 = 3a = 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,就推荐一篇文章,官方文章,讲的很清楚