<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
編寫程式碼過程中, 通常有主協程和多個子協程進行共同作業的過程,比如通過 WaitGroup 可以實現當所有子協程完成之後, 主協程再繼續執行, 具體可參考:Go 中goroutine和WaitGroup的使用
如上的場景是主協程等待子協程達到某個狀態再繼續執行。 但是反過來怎麼操作呢,要求一組子協程等待主協達到某個狀態時才繼續執行。這個時候就需要用到 Cond 了
Cond 是和某個條件相關,在條件還沒有滿足的時候,所有等待這個條件的協程都會被阻塞住,只有這個條件滿足的時候,等待的協程才可能繼續進行下去。
Cond 在初始化的時候,需要關聯一個 Locker 介面的範例,一般會使用 Mutex 或者 RWMutex。
Cond 關聯的 Locker 範例可以通過 c.L 存取,它內部維護著一個先入先出的等待佇列。
Cond 分別有三個方法
會把當前協程放入Cond的等待佇列中並阻塞,直到被Signal或者Broadcast方法從等待佇列中移除並喚醒,用於子協程阻塞。
主協程喚醒等待佇列中的一個子協程,先喚醒最先阻塞的子協程,被喚醒的子協程繼續執行。
主協程喚醒等待佇列中的全部協程,所有子協程繼續執行。
注意:呼叫Signal和Broadcast方法,不強求持有c.L的鎖,呼叫Wait方法是必須要持有c.L的鎖。
大家都去醫院先排隊,然後等待叫號,先排隊的先叫號。這次模擬有5個病人,分別先排隊。 然後護士根據排隊先後來叫號;
具體場景是,5個病人在三秒中之內分別排號,護士今天要叫5個號,一秒叫一個,叫完5個號就結束了
程式碼如下:
package main import ( "fmt" "math/rand" "sync" "time" ) func main() { c := sync.NewCond(&sync.Mutex{}) num := 0 // 當前叫號是幾號 hand_num := 0 for i := 0; i < 5; i++ { go func(i int) { // 分別在不同時間排隊 time.Sleep(time.Second * time.Duration(rand.Int63n(10))) c.L.Lock() num++ // 當前取得號。 cur := num fmt.Printf("%s %d 號病人取到了 %d 號n", time.Now().Format("2006-01-02 15:04:05"), i, cur) // 取到號了,等待叫號 c.Wait() fmt.Printf("%s %d 號病人排隊號是 %d 號,被叫號了n", time.Now().Format("2006-01-02 15:04:05"), i, cur) hand_num = cur c.L.Unlock() }(i) } // 都叫號了 for hand_num != 5 { // 叫號 c.Signal() time.Sleep(time.Second * 1) } time.Sleep(time.Second * 10) }
執行結果如下
結果表明,5個病人,分別在三秒鐘內先後取號, 然後護士每過一秒鐘按照排隊的先後順序叫一個號(叫號的過程依然有病人取號),先取號的被先叫號。
此場景中,5個病人相當於5個協程, 主協程反覆使用Signal()
按照順序一個個喚醒阻塞的子協程。
場景為如下: 運動員跑步比賽,要求8秒內全部運動員準備好,然後等待教練發令, 教練10秒後發令,所有運動員在發令後開始跑。
package main import ( "fmt" "math/rand" "sync" "time" ) func main() { c := sync.NewCond(&sync.Mutex{}) for i := 0; i < 10; i++ { go func(i int) { // 隨機一個8秒內的準備時間 time.Sleep(time.Second * time.Duration(rand.Int63n(8))) fmt.Printf("%s 運動員%d已準備就緒n", time.Now().Format("2006-01-02 15:04:05"), i) c.L.Lock() // 準備完畢,等待教練發令 c.Wait() c.L.Unlock() fmt.Printf("%s 運動員%d開跑n", time.Now().Format("2006-01-02 15:04:05"), i) }(i) } // 主協程等待10秒後發令 time.Sleep(time.Second * 10) fmt.Printf("%s 教練發令。n", time.Now().Format("2006-01-02 15:04:05")) // 教練發令。通知所有運動員開始跑步, 即喚起之前 wait()的所有協程 c.Broadcast() // 等待跑步 time.Sleep(time.Second * 5) }
執行結果如下:
如結果所示, 10個運動員在8秒內分別準備好,等待教練發令後,同時開跑。
此場景中,10個運動員相當於10個協程, 同時等待主協程的命令,使用Broadcast()
喚醒所有阻塞的子協程。
使用 Cond,最容易踩的坑就是呼叫 Wait()
方法之前,呼叫者沒有持有鎖或沒有檢查輔助條件。
在如上範例程式碼中,假如把呼叫 Wait()
方法前後的加鎖和釋放鎖的程式碼註釋掉,執行程式碼會導致程式 panic。原因是呼叫 Wait 方法,會先把呼叫者放入等待佇列中,然後釋放鎖。此時如果在未持有鎖時呼叫釋放鎖的方法,就會導致程式 panic。
到此這篇關於Go中sync 包的 Cond 使用的文章就介紹到這了,更多相關go sync包cond使用內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45