Go Memory Model: https://golang.org/ref/mem
Happens Before
Hanpens Before,为了深入研究同步问题而提出的概念:
- 关于一个变量 v 的读语句
r
与写语句w
,r
可以得到w
的值需要满足以下条件:r
does not happene beforew
;- There is not other
w'
that happens beforer
and afterw
;
- 一个读语句
v
能够准确地捕获到某个特定的w
语句的值,需要满足以下条件:w
happends beforer
;- Any other
w'
to v either hanppends beforew
or afterr
;
Golang Lifetime
Initialization, 一个 golang 程序的初始化:
- 对于库
p
引用库q
的情况,p
的初始化函数开始在q
的初始化函数结束之前; - 在函数
main.main
执行前,所有函数的init
函数都应该执行完成了;
Goroutine destruction:
Goroutine 的销毁不会被保证发生在任何事件之前(not guaranteed to happen before any event)。怎么理解这个
happened before
呢?比如下面这个例子:1 2 3 4 5
var a string func hello() { go func() { a = "hello" }() print(a) }
其中,
a
的赋值语句发生在一个单独的 goroutine 中,它之后没有任何同步语句,所以它有可能不会被任何事件使用,激进一点的编译器会直接拒绝编译。
Communication
Golang 中线程同步的方法。
Channel
Example:
|
|
这段代码一定会输出 hello world
,因为根据上面的理论:
a = "hello world"
happends before<- c
happends beforef()
happends beforeprint(a)
;
Locks
Example:
|
|
上面这段代码一定会输出 hello world
,因为根据理论:
a = "hello world"
happends before 第一个l.Unlock()
happens before 第二个l.Lock()
happens beforeprint(a)
;
Once
Example:
|
|
上面这个代码中保证了 setup
这个函数只能被调用一次,并且 print
一定会输出 hello world
函数,这是因为 once.Do
保证了每次调用都会在第一调用结束之后。