Go的内存模型介绍
Go内存模型指定了一种条件,在一个goroutine中读取到一个变量对其它goroutine写入这个变量的值会是最新即可见性。
Happens Before
在一个单goroutine中,happens-before 顺序会被程序重排。
1,读取变量v被允许看到写后的值,当两者满足下面条件
2,当一个线程读取变量v时,保证这个线程能够获取到特定一个线程写入变量v后的值,并且保证这个写操作是唯一允许这个线程可以获取到最新的值,要保证如下两个条件:
这组条件比第一组条件更加健壮,它需要没有其他写操和以上的读或者写同时发生。
以上条件在单个goroutine上是没有冲突,是有价值的。如果在多个goroutine时,要使用同步机制设置happens-before条件,来保证获取到期望的值。
当初始化变量v为0写入内存时,其数据类型也被写入。
对大于单个机器字符的值的读取和写入,按照未指定的顺序执行多个机器字符大小的操作。
同步
对于go语句开启一个新goroutine发生在这个goroutine执行开始前。 例如,在这个程序:
var a string
func f() {
print(a)
}
func hello() {
a = "hello, world"
go f()
}
在某些情况下调用hello将打印"hello, world"。
Goroutine销毁
goroutine的结束无法保证在这个程序任何事件之前发生。例如,在这个程序:
var a string
func hello() {
go func() { a = "hello" }()
print(a)
}
给变量a赋值不遵循审核同步机制,所以a的最新值无法保证可以被任何其他goroutine获取到。实际上,强大的编译器可能会删除掉那个a全局变量语句。
如果一个goroutine对变量修改必须被其他goroutine获取到,可以使用同步方法,比如加锁,通道传输设置一个稳定的执行顺序。