Golang中的同步工具Sync.WaitGroup詳解
sync.WaitGroup
sync.WaitGroup作用是等待一組goroutine執(zhí)行完成,當(dāng)使用多個(gè)goroutine處理任務(wù)的時(shí)候,如果要等待所有的goroutine都執(zhí)行完成后再執(zhí)行下一步操作,就可以使用sync.WaitGroup來實(shí)現(xiàn)。
sync.WaitGroup有三個(gè)方法:
- Add(delta int):增加或減少等待goroutine的數(shù)量,delta可以為負(fù)數(shù);
- Done():標(biāo)記goroutine已執(zhí)行完成,等價(jià)于Add(-1);
- Wait():等待所有的goroutine執(zhí)行完成。
使用方法和示例
假如有n個(gè)任務(wù)需要處理,可以先創(chuàng)建一個(gè)WaitGroup,用于等待所有的任務(wù)完成:
var wg sync.WaitGroup
在處理每一個(gè)任務(wù)之前,調(diào)用一次Add方法:
wg.Add(1)
在每一個(gè)任務(wù)處理完成之后,調(diào)用一次Done方法:
wg.Done()
最后,在等待所有的任務(wù)完成之前,需要調(diào)用一次Wait方法:
wg.Wait()
具體示例代碼如下:
package main
import (
"log"
"sync"
"time"
)
func main() {
// 創(chuàng)建一個(gè)等待組
var wg sync.WaitGroup
for i := 1; i <= 5; i++ {
// 每一個(gè)任務(wù)開始前, 增加1
wg.Add(1)
go func(index int) {
// 處理業(yè)務(wù)邏輯
//...
time.Sleep(1 * time.Second)
log.Printf("第 %d 個(gè)goroutine執(zhí)行完了", index)
wg.Done()
}(i)
}
// 等待所有的任務(wù)完成
wg.Wait()
log.Println("所有g(shù)oroutine都執(zhí)行完了")
}
使用過程中需要注意的點(diǎn)
- Done和Add方法的順序非常重要,Done方法必須在goroutine最后執(zhí)行,否則可能會(huì)導(dǎo)致計(jì)數(shù)器無法正確的達(dá)到0;
- 如果使用Add或Done方法將wg維護(hù)的計(jì)數(shù)更改成了負(fù)數(shù)會(huì)導(dǎo)致panic;
- Wait方法會(huì)一直阻塞,直到所有的goroutine都執(zhí)行完成為止(wg維護(hù)的計(jì)數(shù)達(dá)到0),因此在使用時(shí)需要小心;
- sync.WaitGroup是開箱即用的,并且是并發(fā)安全的。