Go语言中如何用Mutex配合Goroutine实现锁定与等待?
解决方案:使用sync.WaitGroup实现并发任务启动与等待
你的核心需求是让DoSomething()可以并发调用且立即返回,同时Wait()能确保所有通过DoSomething()启动的goroutine执行完成,避免panic或sys.Exit()导致任务中断。原有的互斥锁方案无法兼顾这两点,推荐使用sync.WaitGroup来实现:
基础实现代码
import "sync" var wg sync.WaitGroup func DoSomething() { // 在启动goroutine前增加任务计数,确保Wait()能感知到该任务 wg.Add(1) go func() { // 确保无论业务代码是否panic,都会标记任务完成 defer wg.Done() // 业务代码 }() } func Wait() { // 阻塞直到所有任务计数被抵消(所有goroutine执行完毕) wg.Wait() }
带临界区保护的实现(如果业务代码需要访问共享资源)
如果你的业务代码需要互斥访问共享资源,只需在goroutine内部添加互斥锁即可,不影响并发启动和等待逻辑:
import "sync" var ( wg sync.WaitGroup lock sync.Mutex ) func DoSomething() { wg.Add(1) go func() { defer wg.Done() lock.Lock() defer lock.Unlock() // 业务代码(安全访问共享资源) }() } func Wait() { wg.Wait() }
为什么原有方案不可行
- 第一种方案(锁在goroutine外):
DoSomething()调用时先获取锁,而锁被goroutine持有直到任务完成,导致后续DoSomething()调用必须等待前一个goroutine释放锁,完全丧失并发能力; - 第二种方案(锁在goroutine内):
Wait()中的锁操作可能在goroutine还未启动(未获取锁)时就执行完毕,无法保证等待所有任务完成。
内容的提问来源于stack exchange,提问作者Dan Jones
相关产品推荐
相关产品推荐

