go條件變數sync.Cond的使用和思考
阿新 • • 發佈:2019-01-07
原始碼採用1.9版本;sync包的Cond,條件變數;在我看來,主要是採用他的wait()方法,來控制被阻塞的go程何時去競爭鎖;我暫且叫它“雙開關控制”(歡迎大神斧正):
廢話少說,來個小例子吧:
package main
import (
"fmt"
"sync"
"time"
)
func main() {
var lc = new(sync.Mutex)
//這個locker 為啥傳入一個引用?
var cond = sync.NewCond(lc)
for i := 0; i < 3; i++ {
go func(x int) {
cond.L.Lock()
defer cond.L.Unlock()
cond.Wait()
fmt.Println(x)
}(i)
}
//睡眠一會,確保下面的Signal()能通知到一個(難道可能通知不到?)
time.Sleep(2*time.Second)
cond.Signal()
cond.Broadcast()
time.Sleep(2*time.Second)
}
執行結果:
0
2
1
上面例子中有兩個問題,我們帶著問題,檢視Cond的一個重要方法:
func (c *Cond) Wait() {
//檢查cond是否被拷貝
c.checker.check()
//將獲得鎖的那個go程加入等待佇列
t := runtime_notifyListAdd(&c.notify)
//釋放鎖(可見呼叫之前要有c.L.lock)
c.L.Unlock()
//go程的等待佇列等待喚醒,這個操作是阻塞的,除非本go程被喚醒
runtime_notifyListWait(&c.notify, t)
//外部記得釋放
c.L.Lock()
}
為啥傳入一個引用?通過wait方法我看到c.L 的操作,如果不是指標變數,也就是發生鎖得拷貝,將導致鎖不統一,從而發生死鎖;
難道可能通知不到?