go WaitGroup的使用
WaitGroup用于等待一組線程的結(jié)束。父線程調(diào)用Add方法來設(shè)定應(yīng)等待的線程的數(shù)量。每個被等待的線程在結(jié)束時應(yīng)調(diào)用Done方法。同時,主線程里可以調(diào)用Wait方法阻塞至所有線程結(jié)束。?
但在使用時,也有一些問題需要注意,請看本文的詳細(xì)分解。?
另外,WaitGroup的使用場景十分有限,為什么呢?具體原因,請看本文的總結(jié)部分的分析。
主要函數(shù)
func (*WaitGroup) Add
func (wg *WaitGroup) Add(delta int)Add方法向內(nèi)部計數(shù)加上delta,delta可以是負(fù)數(shù);如果內(nèi)部計數(shù)器變?yōu)?,Wait方法阻塞等待的所有協(xié)程都會釋放,如果計數(shù)器小于0,則調(diào)用panic。注意Add加上正數(shù)的調(diào)用應(yīng)在Wait之前,否則Wait可能只會等待很少的協(xié)程。一般來說本方法應(yīng)在創(chuàng)建新的協(xié)程或者其他應(yīng)等待的事件之前調(diào)用。
func (wg *WaitGroup) Done()
func (wg *WaitGroup) Done()Done方法減少WaitGroup計數(shù)器的值,應(yīng)在協(xié)程的最后執(zhí)行。
func (wg *WaitGroup) Wait()
func (wg *WaitGroup) Wait()?Wait方法阻塞直到WaitGroup計數(shù)器減為0。
編程實戰(zhàn)
等待某個協(xié)程結(jié)束
func main() {var wg sync.WaitGroupwg.Add(1)go func() {defer wg.Done()fmt.Println("1 goroutine sleep ...")time.Sleep(2e9)fmt.Println("1 goroutine exit ...")}()wg.Add(1)go func() {defer wg.Done()fmt.Println("2 goroutine sleep ...")time.Sleep(4e9)fmt.Println("2 goroutine exit ...")}()fmt.Println("waiting for all goroutine ")wg.Wait()fmt.Println("All goroutines finished!") }小結(jié)
要注意Add和Done函數(shù)一定要配對,否則可能發(fā)生死鎖,所報的錯誤信息如下:
fatal error: all goroutines are asleep - deadlock!
等待協(xié)程組結(jié)束
運行以上程序,輸出如下:
waiting for all goroutine? 1 goroutine start ... 5 goroutine start ... 5 goroutine exit ... 4 goroutine start ... 4 goroutine exit ... 3 goroutine start ... 1 goroutine exit ... 0 goroutine start ... 3 goroutine exit ... 0 goroutine exit ... 2 goroutine start ... 2 goroutine exit ... All goroutines finished!無論運行多少次,都能保證All goroutines finished!這一句在最后一行輸出,這說明,Wait()函數(shù)等了所有協(xié)程都結(jié)束自己才返回。
小結(jié)
以上程序通過WaitGroup提供的三個同步接口,實現(xiàn)了等待一個協(xié)程組完成的同步操作。在實現(xiàn)時要注意:?
* Add的參數(shù)N必須和創(chuàng)建的goroutine的數(shù)量相等,否則會報出死鎖的錯誤信息?
* 另外,sayHello()函數(shù)中要傳遞WaitGroup的指針呢?在該結(jié)構(gòu)的實現(xiàn)源碼中已經(jīng)有講解:
A WaitGroup must not be copied after first use.
就是說,該結(jié)構(gòu)定義后就不能被復(fù)制,所以這里要使用指針。
總結(jié)
通過WaitGroup提供的三個函數(shù):Add,Done,Wait,可以輕松實現(xiàn)等待某個協(xié)程或協(xié)程組完成的同步操作。但在使用時要注意:
Add的數(shù)量和Done的調(diào)用數(shù)量必須相等。
另外,就是WaitGroup結(jié)構(gòu)一旦定義就不能復(fù)制的原因。
WaitGroup在需要等待多個任務(wù)結(jié)束再返回的業(yè)務(wù)來說還是很有用的,但現(xiàn)實中用的更多的可能是,先等待一個協(xié)程組,若所有協(xié)程組都正確完成,則一直等到所有協(xié)程組結(jié)束;若其中有一個協(xié)程發(fā)生錯誤,則告訴協(xié)程組的其他協(xié)程,全部停止運行(本次任務(wù)失敗)以免浪費系統(tǒng)資源。?
該場景WaitGroup是無法實現(xiàn)的,那么該場景該如何實現(xiàn)呢,就需要用到通知機制,其實也可以用channel來實現(xiàn),具體的解決辦法,請看后續(xù)的文章。?
這樣說來,WaitGroup的使用場景是有限的。
總結(jié)
以上是生活随笔為你收集整理的go WaitGroup的使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: redis 慢查询日志
- 下一篇: go WaitGroup 简单示例