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