go runtime_error ai_generated true

panic:sync:WaitGroup 在上一次 Wait 返回前被复用

panic: sync: WaitGroup is reused before previous Wait has returned

ID: go/waitgroup-wait-reused-before-return

其他格式: JSON · Markdown 中文 · English
80%修复率
88%置信度
0证据数
2024-04-18首次发现

版本兼容性

版本状态引入弃用备注
1.20 active — — —
1.21 active — — —
1.22 active — — —

根因分析

在另一个 goroutine 仍阻塞在 Wait() 时调用了 Add(),运行时会禁止此操作以防止计数器竞争。

English

Add() is called on a WaitGroup while another goroutine is still blocked in Wait(), which the runtime forbids to prevent counter races.

generic

解决方案

  1. 95% 成功率
    var wg sync.WaitGroup
    for i := 0; i < n; i++ { wg.Add(1) }
    for i := 0; i < n; i++ {
        go func() { defer wg.Done(); work() }()
    }
    wg.Wait()
  2. 93% 成功率
    sem := make(chan struct{}, 10)
    var wg sync.WaitGroup
    for _, job := range jobs {
        sem <- struct{}{}
        wg.Add(1)
        go func(j Job) {
            defer wg.Done()
            defer func() { <-sem }()
            run(j)
        }(job)
    }
    wg.Wait()

无效尝试

常见但无效的做法:

  1. 80% 失败

    Wait() may return before the goroutine even starts, so Add happens after Wait and the counter update races.

  2. 70% 失败

    Sleep does not synchronize Add with Wait; under load the panic still occurs.