通俗定义

1
2
内存模型描述的是并发环境中多goroutine 读相同变量的时候,变量的可见性条件,具体点说,就是指,在什么条件下,
goroutine 在读取一个变量的值的时候,能够看到其它 goroutine 对这个变量进行的写的结果。

Go内存模型限定了一些条件 满足这些条件 才能让变量 安全地在不同的goroutine之间读写。换句话说就是如何保证在一个 goroutine中看到在另一个goroutine修改的变量的值,如果程序中修改数据时有其他 goroutine 同时读取,那么必须将读取串行化。为了串行化访问,请使用 channel 或其他同步原语,例如 sync 和 sync/atomic 来保护数据。

  1. happens before 谁前谁后
  2. 多个go routine的可见性问题,如果存在多个go routine访问数据的时候,必须序列化访问

单个go routine当中编写 的代码 总是会按照我们的编写代码的顺序来执行

  • 当然这是符合我们的习惯的
  • 当然这并不表示编辑器在编译的时候不会对我们的程序进行指令重排
  • 而是说只会在不影响语言规范的情况下对go routine的行为定义的时候,编辑器和CPU才会对读取与写入的顺序进行重排

happens before(先行发生)的定义

1
2
3
4
5
6
7
当下面条件满足时,对变量 v 的读操作 r 是被允许看到对 v 的写操作 w 的:
1. r 不先行发生于 w
2. 在 w 后 r 前没有对 v 的其他写操作

为了保证对变量 v 的读操作 r 看到对 v 的写操作 w,要确保 w 是 r 允许看到的唯一写操作。即当下面条件满足时,r 被保证看到 w:
1. w 先行发生于 r
2. 其他对共享变量 v 的写操作要么在 w 前,要么在 r 后。

读操作 r 看到最近一次的写操作 w 写入 v 的值。 当多个 goroutine 访问共享变量 v 时,它们必须使用同步事件来建立先行发生这一条件来保证读操作能看到需要的写操作。 对变量 v 的零值初始化在内存模型中表现的与写操作相同。 对大于 single machine word 的变量的读写操作表现的像以不确定顺序对多个 single machine word的变量的操作。

image.png-884.1kB