Go語言等待組sync.WaitGrou的使用示例
Go語言中除了可以使用通道(channel)和互斥鎖進(jìn)行兩個(gè)并發(fā)程序間的同步外,還可以使用等待組進(jìn)行多個(gè)任務(wù)的同步,等待組可以保證在并發(fā)環(huán)境中完成指定數(shù)量的任務(wù)
在 sync.WaitGroup(等待組)類型中,每個(gè) sync.WaitGroup 值在內(nèi)部維護(hù)著一個(gè)計(jì)數(shù),此計(jì)數(shù)的初始默認(rèn)值為零。
等待組有下面幾個(gè)方法可用,如下表所示。
方法名 | 功能 |
---|---|
(wg * WaitGroup) Add(delta int) | 等待組的計(jì)數(shù)器 +1 |
(wg * WaitGroup) Done() | 等待組的計(jì)數(shù)器 -1 |
(wg * WaitGroup) Wait() | 當(dāng)?shù)却M計(jì)數(shù)器不等于 0 時(shí)阻塞直到變 0。 |
對于一個(gè)可尋址的 sync.WaitGroup 值 wg:
- 我們可以使用方法調(diào)用 wg.Add(delta) 來改變值 wg 維護(hù)的計(jì)數(shù)。
- 方法調(diào)用 wg.Done() 和 wg.Add(-1) 是完全等價(jià)的。
- 如果一個(gè) wg.Add(delta) 或者 wg.Done() 調(diào)用將 wg 維護(hù)的計(jì)數(shù)更改成一個(gè)負(fù)數(shù),一個(gè)恐慌將產(chǎn)生。
- 當(dāng)一個(gè)協(xié)程調(diào)用了 wg.Wait() 時(shí),
- 如果此時(shí) wg 維護(hù)的計(jì)數(shù)為零,則此 wg.Wait() 此操作為一個(gè)空操作(noop);
- 否則(計(jì)數(shù)為一個(gè)正整數(shù)),此協(xié)程將進(jìn)入阻塞狀態(tài)。當(dāng)以后其它某個(gè)協(xié)程將此計(jì)數(shù)更改至 0 時(shí)(一般通過調(diào)用 wg.Done()),此協(xié)程將重新進(jìn)入運(yùn)行狀態(tài)(即 wg.Wait() 將返回)。
等待組內(nèi)部擁有一個(gè)計(jì)數(shù)器,計(jì)數(shù)器的值可以通過方法調(diào)用實(shí)現(xiàn)計(jì)數(shù)器的增加和減少。當(dāng)我們添加了 N 個(gè)并發(fā)任務(wù)進(jìn)行工作時(shí),就將等待組的計(jì)數(shù)器值增加 N。每個(gè)任務(wù)完成時(shí),這個(gè)值減 1。同時(shí),在另外一個(gè) goroutine 中等待這個(gè)等待組的計(jì)數(shù)器值為 0 時(shí),表示所有任務(wù)已經(jīng)完成。
下面的代碼演示了這一過程:
package main import ( "fmt" "net/http" "sync" ) func main() { // 聲明一個(gè)等待組 var wg sync.WaitGroup // 準(zhǔn)備一系列的網(wǎng)站地址 var urls = []string{ "http://www.github.com/", "https://www.qiniu.com/", "https://www.golangtc.com/", } // 遍歷這些地址 for _, url := range urls { // 每一個(gè)任務(wù)開始時(shí), 將等待組增加1 wg.Add(1) // 開啟一個(gè)并發(fā) go func(url string) { // 使用defer, 表示函數(shù)完成時(shí)將等待組值減1 defer wg.Done() // 使用http訪問提供的地址 _, err := http.Get(url) // 訪問完成后, 打印地址和可能發(fā)生的錯(cuò)誤 fmt.Println(url, err) // 通過參數(shù)傳遞url地址 }(url) } // 等待所有的任務(wù)完成 wg.Wait() fmt.Println("over") }
代碼說明如下:
- 第 12 行,聲明一個(gè)等待組,對一組等待任務(wù)只需要一個(gè)等待組,而不需要每一個(gè)任務(wù)都使用一個(gè)等待組。
- 第 15 行,準(zhǔn)備一系列可訪問的網(wǎng)站地址的字符串切片。
- 第 22 行,遍歷這些字符串切片。
- 第 25 行,將等待組的計(jì)數(shù)器加1,也就是每一個(gè)任務(wù)加 1。
- 第 28 行,將一個(gè)匿名函數(shù)開啟并發(fā)。
- 第 31 行,在匿名函數(shù)結(jié)束時(shí)會(huì)執(zhí)行這一句以表示任務(wù)完成。wg.Done() 方法等效于執(zhí)行 wg.Add(-1)。
- 第 34 行,使用 http 包提供的 Get() 函數(shù)對 url 進(jìn)行訪問,Get() 函數(shù)會(huì)一直阻塞直到網(wǎng)站響應(yīng)或者超時(shí)。
- 第 37 行,在網(wǎng)站響應(yīng)和超時(shí)后,打印這個(gè)網(wǎng)站的地址和可能發(fā)生的錯(cuò)誤。
- 第 40 行,這里將 url 通過 goroutine 的參數(shù)進(jìn)行傳遞,是為了避免 url 變量通過閉包放入匿名函數(shù)后又被修改的問題。
- 第 44 行,等待所有的網(wǎng)站都響應(yīng)或者超時(shí)后,任務(wù)完成,Wait 就會(huì)停止阻塞。
例子
同時(shí)開三個(gè)協(xié)程去請求網(wǎng)頁, 等三個(gè)請求都完成后才繼續(xù) Wait 之后的工作
var wg sync.WaitGroup var urls = []string{ "http://www.golang.org/", "http://www.google.com/", "http://www.somestupidname.com/", } for _, url := range urls { // Increment the WaitGroup counter. wg.Add(1) // Launch a goroutine to fetch the URL. go func(url string) { // Decrement the counter when the goroutine completes. defer wg.Done() // Fetch the URL. http.Get(url) }(url) } // Wait for all HTTP fetches to complete. wg.Wait()
或者下面的代碼
用于測試 給chan發(fā)送 1千萬次,并接受1千萬次的性能
import ( "fmt" "sync" "time" ) const ( num = 10000000 ) func main() { TestFunc("testchan", TestChan) } func TestFunc(name string, f func()) { st := time.Now().UnixNano() f() fmt.Printf("task %s cost %d \r\n", name, (time.Now().UnixNano()-st)/int64(time.Millisecond)) } func TestChan() { var wg sync.WaitGroup c := make(chan string) wg.Add(1) go func() { for _ = range c { } wg.Done() }() for i := 0; i < num; i++ { c <- "123" } close(c) wg.Wait() }
到此這篇關(guān)于Go語言等待組sync.WaitGrou的使用示例的文章就介紹到這了,更多相關(guān)Go語言等待組sync.WaitGrou內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang限流器time/rate設(shè)計(jì)與實(shí)現(xiàn)詳解
在?Golang?庫中官方給我們提供了限流器的實(shí)現(xiàn)golang.org/x/time/rate,它是基于令牌桶算法(Token?Bucket)設(shè)計(jì)實(shí)現(xiàn)的,下面我們就來看看他的具體使用吧2024-03-03go語言處理TCP拆包/粘包的具體實(shí)現(xiàn)
TCP的拆包/粘包也算是網(wǎng)絡(luò)編程中一個(gè)比較基礎(chǔ)的問題了,本文主要介紹了go語言處理TCP拆包/粘包,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12使用go語言實(shí)現(xiàn)查找兩個(gè)數(shù)組的異同操作
這篇文章主要介紹了使用go語言實(shí)現(xiàn)查找兩個(gè)數(shù)組的異同操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12