Go sync.WaitGroup的用法
介紹
經常會看到以下了代碼:
package mainimport ("fmt""time" )func main(){for i := 0; i < 100 ; i++{go fmt.Println(i)}time.Sleep(time.Second) }主線程為了等待goroutine都運行完畢,不得不在程序的末尾使用time.Sleep() 來睡眠一段時間,等待其他線程充分運行。對于簡單的代碼,100個for循環可以在1秒之內運行完畢,time.Sleep()也可以達到想要的效果。
但是對于實際生活的大多數場景來說,1秒是不夠的,并且大部分時候我們都無法預知for循環內代碼運行時間的長短。這時候就不能使用time.Sleep() 來完成等待操作了。
可以考慮使用管道來完成上述操作:
func main() {c := make(chan bool, 100)for i := 0; i < 100; i++ {go func(i int) {fmt.Println(i)c <- true}(i)}for i := 0; i < 100; i++ {<-c} }首先可以肯定的是使用管道是能達到我們的目的的,而且不但能達到目的,還能十分完美的達到目的。
但是管道在這里顯得有些大材小用,因為它被設計出來不僅僅只是在這里用作簡單的同步處理,在這里使用管道實際上是不合適的。而且假設我們有一萬、十萬甚至更多的for循環,也要申請同樣數量大小的管道出來,對內存也是不小的開銷。
對于這種情況,go語言中有一個其他的工具sync.WaitGroup能更加方便的幫助我們達到這個目的。
WaitGroup 對象內部有一個計數器,最初從0開始,它有三個方法:Add(), Done(), Wait() 用來控制計數器的數量。Add(n)把計數器設置為n ,Done() 每次把計數器-1 ,wait() 會阻塞代碼的運行,直到計數器地值減為0。
使用WaitGroup 將上述代碼可以修改為:
func main() {wg := sync.WaitGroup{}wg.Add(100)for i := 0; i < 100; i++ {go func(i int) {fmt.Println(i)wg.Done()}(i)}wg.Wait() }這里首先把wg 計數設置為100, 每個for循環運行完畢都把計數器減一,主函數中使用Wait() 一直阻塞,直到wg為零——也就是所有的100個for循環都運行完畢。相對于使用管道來說,WaitGroup 輕巧了許多。
注意事項
我們不能使用Add() 給wg 設置一個負值,否則代碼將會報錯:
同樣使用Done() 也要特別注意不要把計數器設置成負數了。
WaitGroup對象不是一個引用類型,在通過函數傳值的時候需要使用地址:
原文鏈接:Golang sync.WaitGroup的用法
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Go sync.WaitGroup的用法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Go 指针 unsafe.Pointer
- 下一篇: PicGo github配置