




下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第Go并發(fā)控制WaitGroup的使用場景分析1.3WaitGroup數(shù)據(jù)結(jié)構(gòu)
源碼包中src/sync/waitgroup.go:WaitGroup定義了其數(shù)據(jù)結(jié)構(gòu):
typeWaitGroupstruct{
state1[3]uint32
}
state1是個長度為3的數(shù)組,其中包含了state和一個信號量,而state實際上是兩個計數(shù)器:
counter:當(dāng)前還未執(zhí)行結(jié)束的goroutine計數(shù)器
waitercount:等待goroutine-group結(jié)束的goroutine數(shù)量,即有多少個等候者
semaphore:信號量
考慮到字節(jié)是否對齊,三者出現(xiàn)的位置不同,為簡單起見,依照字節(jié)已對齊情況下,三者在內(nèi)存中的位置如下所示:
WaitGroup對外提供三個接口:
Add(deltaint):將delta值加到counter中
Wait():waiter遞增1,并阻塞等待信號量semaphore
Done():counter遞減1,按照waiter數(shù)值釋放相應(yīng)次數(shù)信號量
下面分別介紹這三個函數(shù)的實現(xiàn)細(xì)節(jié)。
2.3.1Add()方法
Add()做了兩件事,一是把delta值累加到counter中,因為delta可以為負(fù)值,也就是說counter有可能變成0或負(fù)值,所以第二件事就是當(dāng)counter值變?yōu)?時,根據(jù)waiter數(shù)值釋放等量的信號量,把等待的goroutine全部喚醒,如果counter變?yōu)樨?fù)值,則panic.
Add()偽代碼如下:
func(wg*WaitGroup)Add(deltaint){
statep,semap:=wg.state()//獲取state和semaphore地址指針
state:=atomic.AddUint64(statep,uint64(delta)32)//把delta左移32位累加到state,即累加到counter中
v:=int32(state32)//獲取counter值
w:=uint32(state)//獲取waiter值
ifv0{//經(jīng)過累加后counter值變?yōu)樨?fù)值,panic
panic("sync:negativeWaitGroupcounter")
//經(jīng)過累加后,此時,counter=0
//如果counter為正,說明不需要釋放信號量,直接退出
//如果waiter為零,說明沒有等待者,也不需要釋放信號量,直接退出
ifv0||w==0{
return
//此時,counter一定等于0,而waiter一定大于0(內(nèi)部維護(hù)waiter,不會出現(xiàn)小于0的情況),
//先把counter置為0,再釋放waiter個數(shù)的信號量
*statep=0
for;w!=0;w--{
runtime_Semrelease(semap,false)//釋放信號量,執(zhí)行一次釋放一個,喚醒一個等待者
}
2.3.2Wait()
Wait()方法也做了兩件事,一是累加waiter,二是阻塞等待信號量
func(wg*WaitGroup)Wait(){
statep,semap:=wg.state()//獲取state和semaphore地址指針
for{
state:=atomic.LoadUint64(statep)//獲取state值
v:=int32(state32)//獲取counter值
w:=uint32(state)//獲取waiter值
ifv==0{//如果counter值為0,說明所有g(shù)oroutine都退出了,不需要待待,直接返回
return
//使用CAS(比較交換算法)累加waiter,累加可能會失敗,失敗后通過forloop下次重試
ifatomic.CompareAndSwapUint64(statep,state,state+1){
runtime_Semacquire(semap)//累加成功后,等待信號量喚醒自己
return
}
這里用到了CAS算法保證有多個goroutine同時執(zhí)行Wait()時也能正確累加waiter。
2.3.3Done()
Done()只做一件事,即把counter減1,我們知道Add()可以接受負(fù)值,所以Done實際上只是調(diào)用了Add(-1)。
源碼如下:
func(wg*WaitGroup)Done(){
wg.Add(-1)
}
Done()的執(zhí)行邏輯就轉(zhuǎn)到了Add(),實際上也正是最后一個完成的goroutine把等待者喚醒的。
2.4總結(jié)
簡單說來,WaitGroup通常用于等待一組“工作協(xié)程”結(jié)束的場景,其內(nèi)部維護(hù)兩個計數(shù)器,這里把它們稱為“工作協(xié)程”計數(shù)器和“坐等協(xié)程”計數(shù)器,
WaitGroup對外提供的三個方法分工非常明確:
Add(deltaint)方法用于增加“工作協(xié)程”計數(shù),通常在啟動新的“工作協(xié)程”之前調(diào)用;
Done()方法用于減少“工作協(xié)程”計數(shù),每次調(diào)用遞減1,通常在“工作協(xié)程”內(nèi)部且在臨近返回之前調(diào)用;
Wait()方法用于增加“坐等協(xié)程”計數(shù),通常在所有”工作協(xié)
Done()方法除了負(fù)責(zé)遞減“工作協(xié)程”計數(shù)以外,還會在“工作協(xié)程”計數(shù)變?yōu)?時檢查“坐等協(xié)程”計數(shù)器并把“坐等協(xié)程”喚醒。
需要注意
Done()方法遞減“工作協(xié)程”計數(shù)后,如果“工作協(xié)程”計數(shù)變成負(fù)數(shù)時,將會觸發(fā)panic,這就要求Add()方法調(diào)用要早于Done()方法。
也就是說代碼中,如果調(diào)用Done的次數(shù)多于Add的次數(shù)會產(chǎn)生painc
當(dāng)“工作協(xié)程”計數(shù)多于實際需要等待的“工作協(xié)程”數(shù)量時,“坐等協(xié)程”可能會永遠(yuǎn)無法被喚醒而產(chǎn)生列鎖,此時,Go運行時檢測到死鎖會觸發(fā)panic
Add的添加的工作協(xié)程的數(shù)量,多于Done調(diào)用的次數(shù),則會出現(xiàn)panic
當(dāng)“工作協(xié)程”計數(shù)小于實際需要等待的“工作協(xié)程”數(shù)量時,Done()會在“工作協(xié)程”計數(shù)變?yōu)樨?fù)數(shù)時觸發(fā)panic。
Add()添加的工作協(xié)程個數(shù)小于Done調(diào)用的次數(shù),會出現(xiàn)pani
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年政府引導(dǎo)基金項目申請報告
- 2026年高考政治專項復(fù)習(xí):傳導(dǎo)類試題(解析版)
- 農(nóng)民工工資支付監(jiān)管協(xié)議
- 2025年外研版高中英語必修第一冊Unit6綜合檢測試卷及答案
- 2026年高考適應(yīng)性聯(lián)考日語試卷及答案詳解
- 2025年通信安全員ABC證考試試題
- 《反比例函數(shù)的圖象、性質(zhì)和應(yīng)用(1)》導(dǎo)學(xué)案
- 中華人民共和國的成立和社會主義革命與建設(shè)2(學(xué)生版)
- 辦公室用電安全知識培訓(xùn)課件
- 辦公室人群身材管理課件
- 2-6注塑模模架結(jié)構(gòu)件的設(shè)計
- 某地居民對慢性病患者健康管理的滿意度調(diào)查-以高血壓為例
- 固體礦產(chǎn)鉆探工真題模擬匯編(共634題)
- 高標(biāo)準(zhǔn)農(nóng)田施工組織設(shè)計(全)
- 第34屆全國中學(xué)生物理競賽決賽試題及答案
- 第1章網(wǎng)絡(luò)系統(tǒng)集成概述
- 兒童口腔醫(yī)學(xué)課件 乳牙活髓切斷術(shù)及預(yù)成冠修復(fù)術(shù)
- 風(fēng)險管理01-風(fēng)險及風(fēng)險管理概述
- GB/T 32288-2015電力變壓器用電工鋼鐵心
- 式叉摩那尼戒本
- FZ/T 01008-2008涂層織物耐熱空氣老化性的測定
評論
0/150
提交評論