常常會看到如下了代碼:函數
1 |
package main |
主線程爲了等待goroutine都運行完畢,不得不在程序的末尾使用time.Sleep()
來睡眠一段時間,等待其餘線程充分運行。對於簡單的代碼,100個for循環能夠在1秒以內運行完畢,time.Sleep()
也能夠達到想要的效果。工具
可是對於實際生活的大多數場景來講,1秒是不夠的,而且大部分時候咱們都沒法預知for循環內代碼運行時間的長短。這時候就不能使用time.Sleep()
來完成等待操做了。ui
能夠考慮使用管道來完成上述操做:spa
1 |
func main() { |
首先能夠確定的是使用管道是能達到咱們的目的的,並且不但能達到目的,還能十分完美的達到目的。線程
可是管道在這裏顯得有些大材小用,由於它被設計出來不單單只是在這裏用做簡單的同步處理,在這裏使用管道其實是不合適的。並且假設咱們有一萬、十萬甚至更多的for循環,也要申請一樣數量大小的管道出來,對內存也是不小的開銷。設計
對於這種狀況,go語言中有一個其餘的工具sync.WaitGroup
能更加方便的幫助咱們達到這個目的。指針
WaitGroup
對象內部有一個計數器,最初從0開始,它有三個方法:Add(), Done(), Wait()
用來控制計數器的數量。Add(n)
把計數器設置爲n
,Done()
每次把計數器-1
,wait()
會阻塞代碼的運行,直到計數器地值減爲0。code
使用WaitGroup
將上述代碼能夠修改成:對象
1 |
func main() { |
這裏首先把wg
計數設置爲100, 每一個for循環運行完畢都把計數器減一,主函數中使用Wait()
一直阻塞,直到wg爲零——也就是全部的100個for循環都運行完畢。相對於使用管道來講,WaitGroup
輕巧了許多。進程
咱們不能使用Add()
給wg
設置一個負值,不然代碼將會報錯:
1 |
panic: sync: negative WaitGroup counter |
一樣使用Done()
也要特別注意不要把計數器設置成負數了。
WaitGroup對象不是一個引用類型,在經過函數傳值的時候須要使用地址:
1 |
func main() { |