You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

关于sync.WaitGroup中wg.Add()放置位置的技术疑问

Why does moving wg.Add(1) outside the goroutine ensure v equals 100?

Great question—let’s break this down step by step to make everything clear.

First, let’s recap why your first code snippet fails:

The wg.Add(1) is placed inside the anonymous goroutine. When you launch 100 goroutines with go func(), there’s no guarantee when each goroutine will start executing. The main goroutine might hit wg.Wait() before some (or even many) of the goroutines have run wg.Add(1). Since Wait() unblocks when the wait group counter reaches 0, if the main goroutine gets there before enough Add(1) calls happen, it exits early, leaving some goroutines uncounted. Their atomic.AddInt32 calls might never finish before the program exits, which is why v is always less than 100.

Now let’s look at the fixed version where wg.Add(1) lives inside the loop before launching the goroutine (note: I added the missing parentheses () after the anonymous function—you need those to actually execute the function):

var wg sync.WaitGroup
var v int32 = 0
for i = 0; i < 100; i++{
    wg.Add(1) // Correct: increment counter BEFORE starting the goroutine
    go func(){
        atomic.AddInt32(&v,1)
        wg.Done()
    }()
}
wg.Wait()
fmt.Println(v)

Why this guarantees v equals 100

The critical detail here is that wg.Add(1) runs synchronously in the main goroutine, before we ever launch the corresponding goroutine.

Let’s walk through the flow:

  • For each loop iteration, the main goroutine first increments the wait group counter by 1. This means the counter is guaranteed to account for the goroutine before the goroutine is even scheduled to run.
  • We then launch the goroutine. Even if the goroutine takes time to start executing, the wait group already knows it exists.
  • By the time the main goroutine reaches wg.Wait(), the wait group counter is already at 100 (we ran wg.Add(1) 100 times in the loop). The main goroutine will block until wg.Done() is called exactly 100 times—once for each goroutine.
  • Each goroutine safely increments v with atomic.AddInt32 (which handles concurrent access without race conditions) and then calls wg.Done() to decrement the counter. Once all 100 are done, the counter hits 0, wg.Wait() unblocks, and we print v which is now exactly 100.

Could the main goroutine unblock early?

No, that’s impossible in this setup. Here’s why:

  • The for loop runs entirely synchronously in the main goroutine. We don’t launch any goroutines until after we’ve incremented the wait group counter for that iteration.
  • The main goroutine can’t reach wg.Wait() until it finishes all 100 loop iterations—and thus all 100 wg.Add(1) calls. By the time we get to Wait(), the counter is already at 100, so Wait() will only unblock after all 100 Done() calls are made.

内容的提问来源于stack exchange,提问作者user13505500

火山引擎 最新活动