9.2. Happens Before

在一个单独的goroutine中,变量的读和写操作顺序和代码所写的顺序一致。因此,在变量值没有 被改变的时候, 编译器和处理器可能会记录变量的操作顺序。但是,这种先验性的顺序记录会导致 在两个不同的goroutine对变量操作 顺序记录有差别。例如,一个goroutine执行 a = 1; b = 2; , 但是在另一个goroutine中可能会现感知到b被更新。

为了解决这种二义性问题,Go语言中引进一个happens before的概念,它用于描述 对内存操作的先后顺序问题。如果 事件 e1 happens before 事件 e2,我们说 事件 e2 happens after e1。 如果, 事件e1 does not happen before 事件 e2,并且 does not happen after e2,我们说 事件e1和 e2同时发生

对于一个单一的goroutine,happens before 的顺序和代码的顺序是一致的。

如果能满足以下的条件,一个对变量v的读事件r可以 感知到另一个对变量v的写事件w:

  1. 写事件w happens before 读事件r。
  2. 没有既满足 happens after w 同时满主 happens before r的对变量v的写事件w。

为了保证读事件r可以感知对变量v的写事件,我们首先要 确保w是变量v的唯一的写事件。同时还要满足以下条件:

  1. 写事件w happens before 读事件r。
  2. 其他对变量v的访问必须 happens before 写事件w 或者 happens after 读事件r。

第二组条件比第一组条件更加严格。因为,它要求在w和 r并行执行的程序中不能再有其他的读操作。

对于在单一的goroutine中两组条件是等价的,读事件可以确保感知到对变量的写事件。但是,对于在 两个goroutines共享变量v,我们必须通过同步事件来保证 happens-before 条件 (这是读事件感知写事件的必要条件)。

将变量v自动初始化为零也是属于这个内存操作模型。

读写超过一个机器字长度的数据,顺序也是不能保证的。