版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第詳解Go語(yǔ)言中Goroutine退出機(jī)制的原理及使用}
WaitGroup可以理解為一個(gè)goroutine管理者。他需要知道有多少個(gè)goroutine在給他干活,并且在干完的時(shí)候需要通知他干完了,否則他就會(huì)一直等,直到所有的小弟的活都干完為止。我們加上WaitGroup之后,程序會(huì)進(jìn)行等待,直到它收到足夠數(shù)量的Done()信號(hào)為止。
WaitGroup可被調(diào)用的方法只有三個(gè):Add()、Done()、Wait()。通過(guò)這三個(gè)方法即可實(shí)現(xiàn)上述的功能,下面我們把源碼貼出。
func(wg*WaitGroup)Add(deltaint){
statep:=wg.state()
state:=atomic.AddUint64(statep,uint64(delta)32)
v:=int32(state32)//計(jì)數(shù)器
w:=uint32(state)//等待者個(gè)數(shù)。這里用uint32,會(huì)直接截?cái)嗔烁呶?2位,留下低32位
ifv0{
//Done的執(zhí)行次數(shù)超出Add的數(shù)量
panic("sync:negativeWaitGroupcounter")
ifw!=0delta0v==int32(delta){
//最開(kāi)始時(shí),Wait不能在Add之前被執(zhí)行
panic("sync:WaitGroupmisuse:AddcalledconcurrentlywithWait")
ifv0||w==0{
//計(jì)數(shù)器不為零,還有沒(méi)Done的。return
//沒(méi)有等待者。return
return
//所有g(shù)oroutine都完成任務(wù)了,但有g(shù)oroutine執(zhí)行了Wait后被阻塞,需要喚醒它
if*statep!=state{
//已經(jīng)到了喚醒階段了,就不能同時(shí)并發(fā)Add了
panic("sync:WaitGroupmisuse:AddcalledconcurrentlywithWait")
//清零之后,就可以繼續(xù)Add和Done了
*statep=0
for;w!=0;w--{
//喚醒
runtime_Semrelease(wg.sema,false)
func(wg*WaitGroup)Done(){
wg.Add(-1)
func(wg*WaitGroup)Wait(){
statep:=wg.state()
for{
state:=atomic.LoadUint64(statep)
v:=int32(state32)//計(jì)數(shù)器
w:=uint32(state)//等待者個(gè)數(shù)
ifv==0{
//如果聲明變量后,直接執(zhí)行Wait也不會(huì)有問(wèn)題
//下面CAS操作失敗,重試,但剛好發(fā)現(xiàn)計(jì)數(shù)器變成零了,安全退出
return
ifatomic.CompareAndSwapUint64(statep,state,state+1){
ifrace.Enabledw==0{
race.Write(unsafe.Pointer(wg.sema))
//掛起當(dāng)前的g
runtime_Semacquire(wg.sema)
//被喚醒后,計(jì)數(shù)器不應(yīng)該大于0
//大于0意味著Add的數(shù)量被Done完后,又開(kāi)始了新一波Add
if*statep!=0{
panic("sync:WaitGroupisreusedbeforepreviousWaithasreturned")
return
}
通過(guò)看源碼,我們可以知道,有些使用細(xì)節(jié)是需要注意的:
1.wg.Done()函數(shù)實(shí)際上實(shí)現(xiàn)的是wg.Add(-1),因此直接使用wg.Add(-1)是會(huì)造成同樣的結(jié)果的。在實(shí)際使用中要注意避免誤操作,使得監(jiān)聽(tīng)的goroutine數(shù)量出現(xiàn)誤差。
2.wg.Add()函數(shù)可以一次性加n。但是實(shí)際使用時(shí)通常都設(shè)為1。但是wg本身的counter不能設(shè)為負(fù)數(shù)。假設(shè)你在沒(méi)有Add到10以前,一次性wg.Add(-10),會(huì)出現(xiàn)panic!
packagemain
import(
"fmt"
"sync"
funcmain(){
varwgsync.WaitGroup//定義WaitGroup
arr:=[3]string{"a","b","c"}
for_,v:=rangearr{
wg.Add(1)//增加一個(gè)wait任務(wù)
gofunc(sstring){
deferwg.Done()//函數(shù)結(jié)束時(shí),通知此wait任務(wù)已經(jīng)完成
fmt.Println(s)
}(v)
wg.Add(-10)
//等待所有任務(wù)完成
wg.Wait()
panic:sync:negativeWaitGroupcounter
3.如果你的程序?qū)懙挠袉?wèn)題,出現(xiàn)了始終等待的waitgroup會(huì)造成死鎖。
packagemain
import(
"fmt"
"sync"
funcmain(){
varwgsync.WaitGroup//定義WaitGroup
arr:=[3]string{"a","b","c"}
for_,v:=rangearr{
wg.Add(1)//增加一個(gè)wait任務(wù)
gofunc(sstring){
deferwg.Done()//函數(shù)結(jié)束時(shí),通知此wait任務(wù)已經(jīng)完成
fmt.Println(s)
}(v)
wg.Add(1)
//等待所有任務(wù)完成
wg.Wait()
fatalerror:allgoroutinesareasleep-deadlock!
通過(guò)channel
第二種方法即是通過(guò)channel。具體寫(xiě)法如下:
packagemain
import"fmt"
funcmain(){
arr:=[3]string{"a","b","c"}
ch:=make(chanstruct{},len(arr))
for_,v:=rangearr{
gofunc(sstring){
fmt.Println(s)
ch-struct{}{}
}(v)
fori:=0;ilen(arr);i++{
}
需要注意的是,channel同樣會(huì)導(dǎo)致死鎖。如下方示例:
packagemain
import"fmt"
funcmain(){
arr:=[3]string{"a","b","c"}
ch:=make(chanstruct{},len(arr))
for_,v:=rangearr{
gofunc(sstring){
fmt.Println(s)
ch-struct{}{}
}(v)
fori:=0;ilen(arr);i++{
fatalerror:allgoroutinesareasleep-deadlock!
封裝
利用goroutine的這一特性,我們可以將waitGroup等方式封裝起來(lái),保證goroutine在主進(jìn)程結(jié)束時(shí)會(huì)繼續(xù)執(zhí)行完。封裝demo:
packagemain
import(
"fmt"
"sync"
typeWaitGroupWrapperstruct{
sync.WaitGroup
func(wg*WaitGroupWrapper)Wrap(ffunc(args...interface{}),args...interface{}){
wg.Add(1)
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 沖床模具生產(chǎn)管理制度
- 魚(yú)船安全生產(chǎn)管理制度
- 生產(chǎn)插單計(jì)劃管理制度
- 畜牧安全生產(chǎn)培訓(xùn)制度
- 安全生產(chǎn)班前提醒制度
- 2026上半年云南事業(yè)單位聯(lián)考旅游職業(yè)學(xué)院招聘14人備考考試試題附答案解析
- 安全生產(chǎn)動(dòng)態(tài)監(jiān)管制度
- 2026上海市中醫(yī)醫(yī)院新職工招聘183人(第一批)備考考試題庫(kù)附答案解析
- 雙匯冷鮮肉生產(chǎn)規(guī)章制度
- 生產(chǎn)技術(shù)交底制度
- 智能機(jī)械與機(jī)器人全套課件
- 《2025年CSCO前列腺癌診療指南》更新要點(diǎn)解讀
- 國(guó)有企業(yè)財(cái)務(wù)管理制度
- 河南省鄭州市第六十二中學(xué)2025-2026學(xué)年九年級(jí)上學(xué)期第二次月考語(yǔ)文試題(含答案)
- 2025希臘酸奶行業(yè)市場(chǎng)供需分析及投資評(píng)估規(guī)劃分析研究報(bào)告
- 四川省名校聯(lián)盟2024-2025學(xué)年高二上學(xué)期期末聯(lián)考語(yǔ)文試題含答案2024-2025學(xué)年度上期高二期末聯(lián)考語(yǔ)文試題
- 策劃青少年足球培訓(xùn)計(jì)劃
- 2025年普外副高考試試題及答案
- 餐飲執(zhí)法辦案課件
- 鐵路安全管理?xiàng)l例課件
- 2025年大唐杯試題題庫(kù)及答案
評(píng)論
0/150
提交評(píng)論