golang基礎(chǔ)之waitgroup用法以及使用要點
一、前言
waitgroup在golang中,用于線程同步,指等待一個組,等待一個系列執(zhí)行完成后,才會向下執(zhí)行,可以解決一個 進程goroutine 等待多個該進程啟動的子線程goroutine 都正常運行完成的場景,這個比較常見的場景就是例如 后端 main processer 啟動了多個消費者worker干活,還有爬蟲并發(fā)爬取數(shù)據(jù),多線程下載等等,為了保證主進程在所有的子線程完成后再退出,這時就要用上waitgroup
二、waitgroup使用示例
我們這里模擬一個 worker 的例子
package main import ( "fmt" "sync" "time" ) func worker(idx int, out chan struct{}, wg *sync.WaitGroup) { defer wg.Done() time.Sleep(1 * time.Second) fmt.Println(time.Now()) fmt.Println(idx ) <-out } func main() { wg := new(sync.WaitGroup) in := make(chan struct{}, 20) for i := 0; i < 200; i++ { in <- struct{}{} wg.Add(1) go worker(i, in, wg) } wg.Wait() }
在這段代碼中,main最后一行是
wg.Wait()
這行代碼保證有所的200個子線程全部都執(zhí)行完成后才會退出main函數(shù),如果沒有最后一行wg.Wait(),可能會出現(xiàn)for循環(huán)遍歷完程序就直接退出了,有可能只有不確定個幾個子線程執(zhí)行完成,其它線程由于主程序main退出后就直接退出了
從這個例子我們也可以看到 waitgroup通常配合來限制并發(fā)線程個數(shù)和確保所有的線程都最終都執(zhí)行完成
這段代碼中 ws 有三個緩沖,所以并發(fā)的數(shù)量是20,超過20個就要等待執(zhí)行完成釋放所占用通道后才能再開新的線程
上面的代碼,會在執(zhí)行到wg.Wait()后等待,直到所有的200線程全部執(zhí)行完后才會繼續(xù)往下執(zhí)行
可以説這段代碼非常精妙,示例代碼執(zhí)行結(jié)果如下:
同時我們也可以測試一下把最后一行
//wg.Wait()
注釋掉,我們看一下程序會怎么執(zhí)行
注釋后,我們看到程序完成時,只有171個線程完成運行,剩下的20幾個線程異常結(jié)束了,看不到任何返回結(jié)果
三、waitgroup使用注意事項
同時我們在使用waitgroup時也要注意一些坑:
1、 Add一個負數(shù)
如果計數(shù)器的值小于0會直接panic
2、 Add在Wait之后調(diào)用
比如一些子協(xié)程開頭調(diào)用Add結(jié)束調(diào)用Wait,這些 Wait無法阻塞子協(xié)程。正確做法是在開啟子協(xié)程之前先Add特定的值。
3、 未置為0就重用
WaitGroup可以完成一次編排任務(wù),計數(shù)值降為0后可以繼續(xù)被其他任務(wù)所用,但是不要在還沒使用完的時候就用于其他任務(wù),這樣由于帶著計數(shù)值,很可能出問題。
4、 復(fù)制waitgroup
WaitGroup有nocopy字段,不能被復(fù)制。也意味著WaitGroup不能作為函數(shù)的參數(shù)
四、waitgroup使用總結(jié)
WaitGroup是Golang應(yīng)用開發(fā)過程中經(jīng)常使用的并發(fā)控制技術(shù),學(xué)習(xí)golang是我們必須要掌握和理解的機制之一,建議有時間了大家再進一步的研究一下WaitGroup的底層實現(xiàn)邏輯。
附:陷阱避免
1)WaitGroup 同步的是 goroutine, 如果在 goroutine 中進行 Add(1) 操作,可能在這些 goroutine 還沒來得及 Add(1) 已經(jīng)執(zhí)行 Wait 操作,造成程序退出。
2)WaitGroup 傳遞給goroutine的時候,應(yīng)該采用引用方式,從而避免發(fā)生副本拷貝而死鎖。
總結(jié)
到此這篇關(guān)于golang基礎(chǔ)之waitgroup用法以及使用要點的文章就介紹到這了,更多相關(guān)golang waitgroup用法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go語言遍歷map實現(xiàn)(訪問map中的每一個鍵值對)
這篇文章主要介紹了Go語言遍歷map實現(xiàn)(訪問map中的每一個鍵值對),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01淺談Go語言多態(tài)的實現(xiàn)與interface使用
如果大家系統(tǒng)的學(xué)過C++、Java等語言以及面向?qū)ο蟮脑挘嘈艖?yīng)該對多態(tài)不會陌生。多態(tài)是面向?qū)ο蠓懂牣?dāng)中經(jīng)常使用并且非常好用的一個功能,它主要是用在強類型語言當(dāng)中,像是Python這樣的弱類型語言,變量的類型可以隨意變化,也沒有任何限制,其實區(qū)別不是很大2021-06-06