Golang sync.WaitGroup的用法

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

0x01 介紹

經常會看到以下了代碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
package main

import (
"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() 來完成等待操作了。

可以考慮使用管道來完成上述操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
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) 把計數器設定為nDone() 每次把計數器-1wait() 會阻塞代碼的運行,直到計數器地值減為0。

使用WaitGroup 將上述代碼可以修改為:

1
2
3
4
5
6
7
8
9
10
11
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 輕巧了許多。

0x02 注意事項

1. 計數器不能為負值

我們不能使用Add()wg 設定一個負值,否則代碼將會報錯:

1
2
3
4
5
6
7
panic: sync: negative WaitGroup counter

goroutine 1 [running]:
sync.(*WaitGroup).Add(0xc042008230, 0xffffffffffffff9c)
D:/Go/src/sync/waitgroup.go:75 +0x1d0
main.main()
D:/code/go/src/test-src/2-Package/sync/waitgroup/main.go:10 +0x54

同樣使用Done() 也要特別注意不要把計數器設定成負數了。

2. WaitGroup對象不是一個參考型別

WaitGroup對象不是一個參考型別,在通過函數傳值的時候需要使用地址:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
func main() {
wg := sync.WaitGroup{}
wg.Add(100)
for i := 0; i < 100; i++ {
go f(i, &wg)
}
wg.Wait()
}

// 一定要通過指標傳值,不然進程會進入死結狀態
func f(i int, wg *sync.WaitGroup) {
fmt.Println(i)
wg.Done()
}
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.