package main

import (
	"fmt"
	"sync"
)

var ex, ey int

func main() {
	var ex, ey int
	var ewg sync.WaitGroup
	ewg.Add(2)
	go func() {
		ex = 1
		fmt.Println("ey = ", ey)
		ewg.Done()
	}()
	go func() {
		ey = 1
		fmt.Println("ex = ", ex)
		ewg.Done()
	}()
	ewg.Wait()
}

这一段代码

打印的结果又很多种

ey = 0  ex = 1

ex = 0  ey = 1

ex = 1  ey = 1

ey = 1  ex = 1

但是还有一种结果是: ex = 0  ey = 0,虽然你执行的时候可能不会出现这种情况,但是他确实是存在的

出现这种结果的可能有两个原因:

一,因为赋值和打印的变量不是同一个,所以编译器就可能会认为两条语句的执行顺序不会影响结果,然后就交换了这两个语句的执行顺序

二,两个协程可能在不同的CPU上运行,假设第一个协程在CPU1上运行,第二个协程在CPU2上运行,但是由于每个CPU都会缓存,只有在必要的时候才会写入主内存,其他的CPU才能看到。

CPU1对 ex 进行了修改,但是它只是在自己的本地缓存进行了修改,并没有写入到主内存,所以CPU2看不到,它就打印它上次从主内存取得的过期值。同理CPU1也是打印了 ey 的过期值。所以就会出现 ex和ey同时等于零的情况