定义
- 为了保证共享内存的正确性(可见性,有序性,原子性),内存模型定义了共享内存系统中对多线程程序读写操作行为的规范。
- 通过这些规则来规范对内存的读写操作,从而保证指令正确执行,与处理器、缓存、并发和编译器都有关。
Go的内存模型
- Go 定义了Happens Before:
如果A happens before B,那么A的执行结果对B可见
(并不一定表示A比B先执行)
单线程
- 在单线程环境下,所有表达式按照代码中的先后顺序,具有Happens Before关系。即不管CPU,编译器如何优化,代码从结果看是顺序执行的。
init函数
- 如果包P1 导入了 P2,则
P2的init函数Happens Before所有P1中的操作
。 - main函数Happens
After
所有的init函数。 - 所以流程是,按顺序导入所有被main包导入的包,如果该包又导入了其他包,则继续导入。然后以相反顺序在每个包中初始化常量和变量,并执行init函数。最后调用main函数。
goroutine
- goroutine的创建
Happens Before
所有此goroutine中的操作,销毁Happens After
所有此goroutine的操作。 - 保证创建前修改的数据,在执行时可见。以及执行时修改的数据,在销毁后主Goroutine可见。
channel
- 对一个元素的send操作Happens Before 对应的receive完成操作,保证receive操作在接受完成之前阻塞。
- close操作Happens Before receive端的收到关闭通知操作。
- 对于无缓冲区的channel,对一个元素的receive操作Happens Before对应的send完成操作。保证元素在未接收前,在send端阻塞。
- 对于有缓冲区的channel,第k个receive操作Happens Before第k+c个send完成操作。
lock
- 对于Mutex(互斥锁)/RWMutex(读写锁),第n个解锁操作(unlock)Happens Before 第n+k个加锁(lock)操作。
- 对于RWMutex,存在数值n,加读锁(RLock)操作Happens After 第n个UnLock,其对应的解读锁(RUnLock) Happens Before 第n+1个Lock操作。
- 即Lock总Happens After上一次的Unlock。读写锁的Rlock Happens After上一次的Unlock,对应的RUnlock Happens Before 下一次的Lock。
once
- once.Do 中执行的操作,Happens Before任何once.Do调用的返回(显然before 本次,而其他线程在执行时阻塞,所以也before他们)