首先,先看看这一段代码
var x, y int
func main() {
go func() {
x = 1
fmt.Println("y = ", y)
}()
go func() {
y = 1
fmt.Println("x = ", x)
}()
time.Sleep(time.Second)
}
打印的结果又很多种
y = 0 x = 1
x = 0 y = 1
x = 1 y = 1
y = 1 x = 1
但是还有一种结果是: x = 0 y = 0,虽然你执行的时候可能不会出现这种情况,但是他确实是存在的
出现这种结果的可能有两个原因:
一,
因为赋值和打印的变量不是同一个,所以编译器就可能会认为两条语句的执行顺序不会影响结果,然后就交换了这两个语句的执行顺序
二,
两个协程可能在不同的CPU上运行,假设第一个协程在CPU1上运行,第二个协程在CPU2上运行,但是由于每个CPU都会缓存,只有在必要的时候才会写入主内存,其他的CPU才能看到。
CPU1对 x 进行了修改,但是它只是在自己的本地缓存进行了修改,并没有写入到主内存,所以CPU2看不到,它就打印它上次从主内存取得的过期值。同理CPU1也是打印了 y 的过期值。所以就会出现 x和y同时等于零的情况