问: 了解过go的内存模型吗?大概讲一讲

答: Go内存模型指定了一系列条件,在这些条件下,可以保证在一个goroutine中读取变量可以观察到其他goroutine中对同一变量所写的值。即安全的在不同的协程中读写变量。

问:为什么需要有这些条件呢?

答:编译器或处理器不保证指令执行顺序和程序书写顺序一致,同时读写变量由于变量体积不同,也不一定是原子性的。

问:举一个理论上不保证能读到写的例子,并解释。

答:

在go出来的goroutine中的写入和下面对i的读取之间没有同步事件来建立happens before关系。

问:在Go语言中有哪些可以建立happens before关系的同步事件。

答:

包初始化 init函数。

如果一个包 p 导入了包 q,那么 q 的 init 函数完成happens before p 的 init 。main.main 函数的开始happens after 所有的 init 函数完成。

创建goroutine

创建goroutine happens before goroutine执行

销毁goroutine

goroutine执行happens before goroutine的销毁

channel

  1. 对channel的关闭先行发生于接收到0值,因为channel已经被关闭了。

2. 无缓冲channel的接收先行发生于发送完成。

3. 在容量为C的channel上的第k个接收先行发生于从这个channel上的第k+C次发送完成。

  1. 对任意的sync.Mutex或sync.RWMutex变量l和n < m,n次调用l.Unlock()先行发生于m次l.Lock()返回

2. 对于sync.RWMutex变量l,任意的函数调用l.RLock满足第n次l.RLock后发生于第n次调用l.Unlock,对应的l.RUnlock先行发生于第n+1次调用l.Lock

Once

对于 f() 的单个调用在所有的 once.Do(f) 返回之前发生。