網站首頁 編程語言 正文
一、前言
waitgroup在golang中,用于線程同步,指等待一個組,等待一個系列執行完成后,才會向下執行,可以解決一個 進程goroutine 等待多個該進程啟動的子線程goroutine 都正常運行完成的場景,這個比較常見的場景就是例如 后端 main processer 啟動了多個消費者worker干活,還有爬蟲并發爬取數據,多線程下載等等,為了保證主進程在所有的子線程完成后再退出,這時就要用上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個子線程全部都執行完成后才會退出main函數,如果沒有最后一行wg.Wait(),可能會出現for循環遍歷完程序就直接退出了,有可能只有不確定個幾個子線程執行完成,其它線程由于主程序main退出后就直接退出了
從這個例子我們也可以看到 waitgroup通常配合來限制并發線程個數和確保所有的線程都最終都執行完成
這段代碼中 ws 有三個緩沖,所以并發的數量是20,超過20個就要等待執行完成釋放所占用通道后才能再開新的線程
上面的代碼,會在執行到wg.Wait()后等待,直到所有的200線程全部執行完后才會繼續往下執行
可以説這段代碼非常精妙,示例代碼執行結果如下:
同時我們也可以測試一下把最后一行
//wg.Wait()
注釋掉,我們看一下程序會怎么執行
注釋后,我們看到程序完成時,只有171個線程完成運行,剩下的20幾個線程異常結束了,看不到任何返回結果
三、waitgroup使用注意事項
同時我們在使用waitgroup時也要注意一些坑:
1、 Add一個負數
如果計數器的值小于0會直接panic
2、 Add在Wait之后調用
比如一些子協程開頭調用Add結束調用Wait,這些 Wait無法阻塞子協程。正確做法是在開啟子協程之前先Add特定的值。
3、 未置為0就重用
WaitGroup可以完成一次編排任務,計數值降為0后可以繼續被其他任務所用,但是不要在還沒使用完的時候就用于其他任務,這樣由于帶著計數值,很可能出問題。
4、 復制waitgroup
WaitGroup有nocopy字段,不能被復制。也意味著WaitGroup不能作為函數的參數
四、waitgroup使用總結
WaitGroup是Golang應用開發過程中經常使用的并發控制技術,學習golang是我們必須要掌握和理解的機制之一,建議有時間了大家再進一步的研究一下WaitGroup的底層實現邏輯。
附:陷阱避免
1)WaitGroup 同步的是 goroutine, 如果在 goroutine 中進行 Add(1) 操作,可能在這些 goroutine 還沒來得及 Add(1) 已經執行 Wait 操作,造成程序退出。
2)WaitGroup 傳遞給goroutine的時候,應該采用引用方式,從而避免發生副本拷貝而死鎖。
總結
原文鏈接:https://blog.csdn.net/itopit/article/details/125525681
相關推薦
- 2022-05-18 python?中賦值,深拷貝,淺拷貝的區別_python
- 2022-08-10 C++中string字符串分割函數split()的4種實現方法_C 語言
- 2022-04-07 Kotlin原理詳析之拓展函數_Android
- 2022-07-16 Linux Redis-6.2.6單機部署
- 2023-01-10 Qt實現可以計算大數的簡單計算器_C 語言
- 2022-01-31 關于el-form中的rules未生效問題的解決方法
- 2022-06-13 harbor可視化私有鏡像倉庫環境及服務部署示例_docker
- 2022-11-28 深入了解C++函數重載解析策略_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支