Go 中 sync.WaitGroup 与 sync.Mutex 组合可协调 goroutine 生命周期与共享资源访问:WaitGroup 通过 Add/Wait/Done 控制任务启停,Mutex 通过锁机制防止数据竞争,二者分工明确、配合自然。
使用 Go 的 sync.WaitGroup 和 sync.Mutex 组合,能有效协调多个 goroutine 的生命周期与共享资源访问——WaitGroup 负责“等任务完成”,Mutex 负责“防数据竞争”,二者分工明确,配合自然。
WaitGroup 适合管理一组并发任务的启动与等待。它不关心任务内部逻辑,只跟踪“谁还没结束”。核心是三个方法:Add()(预设任务数)、Done()(标记完成)、Wait()(阻塞直到全部完成)。
Add(1),不能在 goroutine 内部 Add —— 否则可能 Wait 提前返回Done() 应该和 Add(1) 严格配对;推荐用 defer wg.Done() 避免遗漏当多个 goroutine 共同更新一个变量(如计数器、切片、map)时,必须用 Mutex 加锁。它不控制执行顺序,只确保同一时刻最多一个 goroutine 进入临界区。
mu.Lock()/mu.Unlock() 配对,或更稳妥地用 defer mu.Unlock()
典型场景是并发处理一批数据,并汇总结果(比如统计成功/失败数量、收集返回值)。WaitGroup 确保主协程不提前退出,Mutex 保证汇总操作线程安全。
示例逻辑:
var success, fail int; var mu sync.Mutex
mu.Lock(); success++; mu.Unlock() 或类似操作wg.Wait() 后,再安全读取 success 和 fail
注意:不要把 mu.Lock() 放在 WaitGroup 的 Add/Wait 调用路径上——它们无需同步,加锁只会拖慢调度。
对于简单计数,可考虑 sync/atomic(如 atomic.AddInt64),它比 Mutex 更轻量且无锁;但仅适用于基础类型和有限操作。若需复杂结构(如向切片追加、修改 map),仍需 Mutex。
另外,WaitGroup 无法取消或超时;如有此需求,应结合 context.Context 控制 goroutine 生命周期,WaitGroup 仅用于收尾等待。