条件变量 sync.Cond
sync.Cond 條件變量是基于互斥鎖的,它必須有互斥鎖的支撐才能發(fā)揮作用。
- sync.Cond 條件變量用來(lái)協(xié)調(diào)想要訪問(wèn)共享資源的那些線程,當(dāng)共享資源的狀態(tài)發(fā)生變化的時(shí)候,它可以用來(lái)通知被互斥鎖阻塞的線程
- 條件變量的初始化離不開(kāi)互斥鎖,并且它的方法也是基于互斥鎖的
- 條件變量有三個(gè)方法,等待通知(wait),單發(fā)通知(signal),廣播通知(broadcast)。當(dāng)互斥鎖鎖定時(shí),可以進(jìn)行等待通知;當(dāng)互斥鎖解鎖時(shí),可以進(jìn)行單發(fā)通知和廣播通知。
有幾個(gè)點(diǎn)需要知道
- sync.Cond 通過(guò)sync.NewCond(sync.Locker)初始化,初始化函數(shù)需要一個(gè)sync.Locker的參數(shù)值
- sync.Locker其實(shí)是一個(gè)接口,包含Lock()和Unlock()方法。sync.Mutex和sync.RWMutex都有Lock和Unlock方法,只不過(guò)它們都是指針?lè)椒āR虼?#xff0c;這兩個(gè)類型的指針類型才是sync.Locker接口的實(shí)現(xiàn)類型
- 通過(guò)lock.RLock()獲得讀鎖,這個(gè)讀鎖能調(diào)用lock變量的RLock和RUnlock方法,實(shí)現(xiàn)對(duì)讀鎖的解鎖和鎖定。
生產(chǎn)者,這里看作向mailbox產(chǎn)生值的對(duì)象
lock.Lock() for mailbox == 1 {sendCond.Wait() } mailbox = 1 lock.Unlock() recvCond.Signal()消費(fèi)者,向mailbox取值的對(duì)象
lock.RLock() for mailbox == 0 {recvCond.Wait() } mailbox = 0 lock.RUnlock() sendCond.Signal()條件變量的Wait方法主要做了四件事。
- 把調(diào)用它的 goroutine(也就是當(dāng)前的 goroutine)加入到當(dāng)前條件變量的通知隊(duì)列中。
- 解鎖當(dāng)前的條件變量基于的那個(gè)互斥鎖。
- 讓當(dāng)前的 goroutine 處于等待狀態(tài),等到通知到來(lái)時(shí)再?zèng)Q定是否喚醒它。此時(shí),這個(gè) goroutine 就會(huì)阻塞在調(diào)用這個(gè)Wait方法的那行代碼上。
- 如果通知到來(lái)并且決定喚醒這個(gè) goroutine,那么就在喚醒它之后重新鎖定當(dāng)前條件變量基于的互斥鎖。自此之后,當(dāng)前的 goroutine 就會(huì)繼續(xù)執(zhí)行后面的代碼了。
if語(yǔ)句只會(huì)對(duì)共享資源的狀態(tài)檢查一次,而for語(yǔ)句卻可以做多次檢查,直到這個(gè)狀態(tài)改變?yōu)橹埂D菫槭裁匆龆啻螜z查呢?這主要是為了保險(xiǎn)起見(jiàn)。如果一個(gè) goroutine 因收到通知而被喚醒,但卻發(fā)現(xiàn)共享資源的狀態(tài),依然不符合它的要求,那么就應(yīng)該再次調(diào)用條件變量的Wait方法,并繼續(xù)等待下次通知的到來(lái)。
在 Go 語(yǔ)言中,我們需要用sync.NewCond函數(shù)來(lái)初始化一個(gè)sync.Cond類型的條件變量。
sync.NewCond函數(shù)需要一個(gè)sync.Locker類型的參數(shù)值。
sync.Mutex類型的值以及sync.RWMutex類型的值都可以滿足這個(gè)要求。都可以滿足這個(gè)要求。另外,后者的RLocker方法可以返回這個(gè)值中的讀鎖,也同樣可以作為sync.NewCond函數(shù)的參數(shù)值,如此就可以生成與讀寫(xiě)鎖中的讀鎖對(duì)應(yīng)的條件變量了。
條件變量的Wait方法需要在它基于的互斥鎖保護(hù)下執(zhí)行,否則就會(huì)引發(fā)不可恢復(fù)的 panic。此外,我們最好使用for語(yǔ)句來(lái)檢查共享資源的狀態(tài),并包裹對(duì)條件變量的Wait方法的調(diào)用。
不要用if語(yǔ)句,因?yàn)樗荒苤貜?fù)地執(zhí)行”檢查狀態(tài) - 等待通知 - 被喚醒“的這個(gè)流程。重復(fù)執(zhí)行這個(gè)流程的原因是,一個(gè)因等待通知,而被阻塞的 goroutine,可能會(huì)在共享資源的狀態(tài)不滿足其要求的情況下被喚醒。
條件變量的Signal方法只會(huì)喚醒一個(gè)因等待通知而被阻塞的 goroutine,而它的Broadcast方法卻可以喚醒所有為此而等待的 goroutine。后者比前者的適應(yīng)場(chǎng)景要多得多。
這兩個(gè)方法并不需要受到互斥鎖的保護(hù),我們也最好不要在解鎖互斥鎖之前調(diào)用它們。還有,條件變量的通知具有即時(shí)性。當(dāng)通知被發(fā)送的時(shí)候,如果沒(méi)有任何 goroutine 需要被喚醒,那么該通知就會(huì)立即失效。
轉(zhuǎn)載于:https://www.cnblogs.com/linyihai/p/10253339.html
總結(jié)
以上是生活随笔為你收集整理的条件变量 sync.Cond的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 微信小程序页面跳转、逻辑层模块化
- 下一篇: 安阳治疗女性卵巢多囊最好的医院推荐