You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

sync: WaitGroup在Wait返回前被复用引发Panic问题咨询

问题:sync.WaitGroup 触发 panic: sync: WaitGroup is reused before previous Wait has returned

生产环境中大量goroutine并发运行以下代码片段时,一段时间后触发panic:sync: WaitGroup is reused before previous Wait has returned。将WaitGroup设为全局变量可复现该问题,但当前提供的代码片段无法直接复现。

关键代码片段

func check() {

    .......check condition......

    //skipEnsure and skipNative will not both false here
    var wg sync.WaitGroup
    if !skipEnsure {
        wg.Add(1)
        go func(wg *sync.WaitGroup) {
            defer wg.Done()
            dosomething1()
        }(&wg)
    }
    if !skipNative {
        wg.Add(1)
        go func(wg *sync.WaitGroup) {
            defer wg.Done()
            dosomething2()
        }(&wg)
    }
    wg.Wait() //panic here
}

func worker() {
    ......

    go check()
}

func main() {
    for i:=0;i<32;i++ {
        go worker()
    }
    ch := make(chan any, 0)
    <-ch
}

问题原因

  • 你提供的代码中WaitGroup是check函数的局部变量,理论上每次调用check都会创建新实例,不会出现复用冲突。但生产环境触发panic,说明实际代码里的WaitGroup并非每次调用都新建——大概率是被定义在check外部(比如全局变量、闭包捕获的外部变量、结构体字段等),导致多个goroutine同时复用同一个WaitGroup实例。
  • sync.WaitGroup的设计是单次使用:完成Wait()后,不能再调用Add()并重新执行Wait(),否则会触发该panic。当多个goroutine同时对同一个WaitGroup执行Add()、Wait()操作时,就会出现“前一次Wait还未返回就被复用”的冲突。

解决方法

  • 优先方案:每次使用新建WaitGroup实例:保持var wg sync.WaitGroup在check函数内部,确保每个check调用都使用独立的WaitGroup实例,从根源避免复用冲突。
  • 若必须复用(不推荐):需用sync.Mutex互斥锁保护WaitGroup的所有操作(Add()、Wait()、Done()),确保同一时间只有一个goroutine操作该WaitGroup,且严格遵循“Add -> 启动goroutine -> Wait -> 重置(仅确认所有Done执行完毕后)”的顺序,但这种方式会削弱并发性能,不建议采用。

内容的提问来源于stack exchange,提问作者jx.wtj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 06:02:08