sync.WaitGroup通过计数器协调goroutine完成。1. 初始化后,在启动goroutine前调用Add增加计数;2. 每个goroutine结束时调用Done减少计数,推荐使用defer wg.Done()确保执行;3. 主goroutine调用Wait阻塞,直到计数器归零。常见陷阱是Add调用时机错误,必须在go语句前执行,否则可能导致竞态条件或死锁。最佳实践包括:始终在启动goroutine前Add,使用defer wg.Done()保证通知,避免复制WaitGroup。

sync.WaitGroup
在Golang中主要通过一个内部计数器来协调goroutine的完成。当需要等待一组goroutine时,我们会在启动它们之前调用
Add
方法增加计数,每个goroutine完成任务后调用
Done
方法递减计数。主goroutine则通过调用
Wait
方法阻塞,直到这个计数器归零,表示所有被追踪的goroutine都已完成。
当我们在Golang中处理并发任务时,经常会遇到一个场景:启动多个goroutine去执行一些工作,然后主goroutine需要等待所有这些子goroutine都完成,才能继续执行后续逻辑,或者安全地退出程序。
sync.WaitGroup
就是为此而生的。
它的核心机制其实很简单:
初始化:声明一个
var wg sync.WaitGroup
。计数器增加:在启动任何需要等待的goroutine之前,调用
wg.Add(delta int)
。这个
delta
通常是你即将启动的goroutine数量。每调用一次
Add(1)
,内部计数器就加一。任务完成通知:在每个goroutine内部,当其任务即将完成时,调用
wg.Done()
。这会将内部计数器减一。一个非常好的实践是使用
defer wg.Done()
,这样即使goroutine内部发生panic,
Done()
也能被执行,避免主goroutine永远等待。等待:在主goroutine中,调用
wg.Wait()
。这个方法会阻塞当前goroutine,直到
WaitGroup
的内部计数器变为零。
来看个例子,这能让你更直观地理解:
立即学习“go语言免费学习笔记(深入)”;
package mainimport ( "fmt" "sync" "time")func worker(id int, wg *sync.WaitGroup) { // 确保无论如何,这个goroutine完成时都会通知WaitGroup defer wg.Done() fmt.Printf("Worker %d starting...n", id) time.Sleep(time.Duration(id) * time.Second) // 模拟工作 fmt.Printf("Worker %d finished.n", id)}func main() { var wg sync.WaitGroup numWorkers := 3 fmt.Println("Main: Launching workers...") for i := 1; i <= numWorkers; i++ { wg.Add(1) // 每启动一个worker,计数器加1 go worker(i, &wg) } fmt.Println("Main: Waiting for all workers to complete...") wg.Wait() // 阻塞直到所有worker都调用了Done() fmt.Println("Main: All workers completed. Exiting.")}
运行这段代码,你会看到主goroutine在启动所有
worker
之后,会一直等到所有
worker
都打印出”finished”才继续执行
"Main: All workers completed. Exiting."
。这正是我们想要的效果。
我个人在使用
WaitGroup
时,最常犯的一个小错误,或者说容易忽略的细节,就是
Add
的时机。它必须在对应的
go
语句之前调用。如果你在
go worker(i, &wg)
之后才
wg.Add(1)
,那么在某些极端情况下,如果
worker
执行得特别快,可能在
Add
被调用之前就已经
Done
了,这会导致计数器不匹配,
Wait
可能会提前返回或者永远等待。所以,顺序很重要。
Golang
sync.WaitGroup
sync.WaitGroup
有哪些常见的陷阱和最佳实践?
在使用
sync.WaitGroup
时,虽然它看起来直观,但
以上就是sync.WaitGroup在Golang中如何等待所有goroutine完成任务的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1401612.html
微信扫一扫
支付宝扫一扫