




下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第Go并發(fā)控制WaitGroup的使用場(chǎng)景分析1.3WaitGroup數(shù)據(jù)結(jié)構(gòu)
源碼包中src/sync/waitgroup.go:WaitGroup定義了其數(shù)據(jù)結(jié)構(gòu):
typeWaitGroupstruct{
state1[3]uint32
}
state1是個(gè)長度為3的數(shù)組,其中包含了state和一個(gè)信號(hào)量,而state實(shí)際上是兩個(gè)計(jì)數(shù)器:
counter:當(dāng)前還未執(zhí)行結(jié)束的goroutine計(jì)數(shù)器
waitercount:等待goroutine-group結(jié)束的goroutine數(shù)量,即有多少個(gè)等候者
semaphore:信號(hào)量
考慮到字節(jié)是否對(duì)齊,三者出現(xiàn)的位置不同,為簡單起見,依照字節(jié)已對(duì)齊情況下,三者在內(nèi)存中的位置如下所示:
WaitGroup對(duì)外提供三個(gè)接口:
Add(deltaint):將delta值加到counter中
Wait():waiter遞增1,并阻塞等待信號(hào)量semaphore
Done():counter遞減1,按照waiter數(shù)值釋放相應(yīng)次數(shù)信號(hào)量
下面分別介紹這三個(gè)函數(shù)的實(shí)現(xiàn)細(xì)節(jié)。
2.3.1Add()方法
Add()做了兩件事,一是把delta值累加到counter中,因?yàn)閐elta可以為負(fù)值,也就是說counter有可能變成0或負(fù)值,所以第二件事就是當(dāng)counter值變?yōu)?時(shí),根據(jù)waiter數(shù)值釋放等量的信號(hào)量,把等待的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)過累加后,此時(shí),counter=0
//如果counter為正,說明不需要釋放信號(hào)量,直接退出
//如果waiter為零,說明沒有等待者,也不需要釋放信號(hào)量,直接退出
ifv0||w==0{
return
//此時(shí),counter一定等于0,而waiter一定大于0(內(nèi)部維護(hù)waiter,不會(huì)出現(xiàn)小于0的情況),
//先把counter置為0,再釋放waiter個(gè)數(shù)的信號(hào)量
*statep=0
for;w!=0;w--{
runtime_Semrelease(semap,false)//釋放信號(hào)量,執(zhí)行一次釋放一個(gè),喚醒一個(gè)等待者
}
2.3.2Wait()
Wait()方法也做了兩件事,一是累加waiter,二是阻塞等待信號(hào)量
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,累加可能會(huì)失敗,失敗后通過forloop下次重試
ifatomic.CompareAndSwapUint64(statep,state,state+1){
runtime_Semacquire(semap)//累加成功后,等待信號(hào)量喚醒自己
return
}
這里用到了CAS算法保證有多個(gè)goroutine同時(shí)執(zhí)行Wait()時(shí)也能正確累加waiter。
2.3.3Done()
Done()只做一件事,即把counter減1,我們知道Add()可以接受負(fù)值,所以Done實(shí)際上只是調(diào)用了Add(-1)。
源碼如下:
func(wg*WaitGroup)Done(){
wg.Add(-1)
}
Done()的執(zhí)行邏輯就轉(zhuǎn)到了Add(),實(shí)際上也正是最后一個(gè)完成的goroutine把等待者喚醒的。
2.4總結(jié)
簡單說來,WaitGroup通常用于等待一組“工作協(xié)程”結(jié)束的場(chǎng)景,其內(nèi)部維護(hù)兩個(gè)計(jì)數(shù)器,這里把它們稱為“工作協(xié)程”計(jì)數(shù)器和“坐等協(xié)程”計(jì)數(shù)器,
WaitGroup對(duì)外提供的三個(gè)方法分工非常明確:
Add(deltaint)方法用于增加“工作協(xié)程”計(jì)數(shù),通常在啟動(dòng)新的“工作協(xié)程”之前調(diào)用;
Done()方法用于減少“工作協(xié)程”計(jì)數(shù),每次調(diào)用遞減1,通常在“工作協(xié)程”內(nèi)部且在臨近返回之前調(diào)用;
Wait()方法用于增加“坐等協(xié)程”計(jì)數(shù),通常在所有”工作協(xié)
Done()方法除了負(fù)責(zé)遞減“工作協(xié)程”計(jì)數(shù)以外,還會(huì)在“工作協(xié)程”計(jì)數(shù)變?yōu)?時(shí)檢查“坐等協(xié)程”計(jì)數(shù)器并把“坐等協(xié)程”喚醒。
需要注意
Done()方法遞減“工作協(xié)程”計(jì)數(shù)后,如果“工作協(xié)程”計(jì)數(shù)變成負(fù)數(shù)時(shí),將會(huì)觸發(fā)panic,這就要求Add()方法調(diào)用要早于Done()方法。
也就是說代碼中,如果調(diào)用Done的次數(shù)多于Add的次數(shù)會(huì)產(chǎn)生painc
當(dāng)“工作協(xié)程”計(jì)數(shù)多于實(shí)際需要等待的“工作協(xié)程”數(shù)量時(shí),“坐等協(xié)程”可能會(huì)永遠(yuǎn)無法被喚醒而產(chǎn)生列鎖,此時(shí),Go運(yùn)行時(shí)檢測(cè)到死鎖會(huì)觸發(fā)panic
Add的添加的工作協(xié)程的數(shù)量,多于Done調(diào)用的次數(shù),則會(huì)出現(xiàn)panic
當(dāng)“工作協(xié)程”計(jì)數(shù)小于實(shí)際需要等待的“工作協(xié)程”數(shù)量時(shí),Done()會(huì)在“工作協(xié)程”計(jì)數(shù)變?yōu)樨?fù)數(shù)時(shí)觸發(fā)panic。
Add()添加的工作協(xié)程個(gè)數(shù)小于Done調(diào)用的次數(shù),會(huì)出現(xiàn)pani
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 托班水果黏土手工課程設(shè)計(jì)
- 跳棋競(jìng)技賽事活動(dòng)計(jì)劃
- 2025年中小學(xué)法治教育工作計(jì)劃范文
- 2024-2025學(xué)年度第二學(xué)期學(xué)科競(jìng)賽組織計(jì)劃
- 四年級(jí)春季語文主題探究計(jì)劃
- 歷史主題探究活動(dòng)計(jì)劃
- 退休人員外包服務(wù)協(xié)議
- 蘇教版六年級(jí)科學(xué)文化交流計(jì)劃
- 零部件采購與維修合同
- 銷售激勵(lì)大會(huì)服務(wù)協(xié)議
- UML面向?qū)ο笤O(shè)計(jì)與分析教程配套課件
- CJ∕T 51-2018 城鎮(zhèn)污水水質(zhì)標(biāo)準(zhǔn)檢驗(yàn)方法
- 職業(yè)技術(shù)學(xué)院《酒店管理概論》課程標(biāo)準(zhǔn)
- 煙花爆竹零售經(jīng)營場(chǎng)所安全管理新規(guī)制度
- 青綠色中國農(nóng)業(yè)科學(xué)院考研復(fù)試模板
- 能源轉(zhuǎn)型與綠色發(fā)展
- 2024年杭州錢塘新區(qū)產(chǎn)業(yè)發(fā)展集團(tuán)有限公司招聘筆試沖刺題(帶答案解析)
- 數(shù)字經(jīng)濟(jì)下平臺(tái)化人力資源管理對(duì)員工創(chuàng)新績效的影響研究-數(shù)字能力的調(diào)節(jié)效應(yīng)
- 建筑工程 施工組織設(shè)計(jì)范本
- 三亞旅游宣傳含內(nèi)容
- 2024年浙江省寧波市鄞州區(qū)部分學(xué)校九年級(jí)6月中考聯(lián)考英語試卷
評(píng)論
0/150
提交評(píng)論