In the Go code below, the variable v is often less than expected due to an incorrect placement of wg.Add().
<code class="go">var wg sync.WaitGroup var v int32 = 0 for i := 0; i < 100; i++ { go func() { wg.Add(1) // Wrong place atomic.AddInt32(&v, 1) wg.Done() } } wg.Wait() fmt.Println(v)</code>
wg.Add() should always be called before launching the corresponding goroutine to ensure that the main goroutine blocks until all goroutines have executed wg.Done().
<code class="go">var wg sync.WaitGroup var v int32 = 0 for i := 0; i < 100; i++ { wg.Add(1) go func() { atomic.AddInt32(&v, 1) wg.Done() } } wg.Wait() fmt.Println(v)</code>
When wg.Add() is placed inside the goroutine, it cannot guarantee that the main goroutine will block until all goroutines complete. This is because the goroutines run concurrently and the order of execution is non-deterministic.
By placing wg.Add() before the goroutine, we ensure that the main goroutine calls wg.Add() 100 times before reaching wg.Wait(). This ensures that the main goroutine blocks until all 100 goroutines have called wg.Done(), resulting in v being consistently equal to 100.
When using sync.WaitGroup, follow these guidelines:
The above is the detailed content of Why is wg.Add() Placement Crucial for Guaranteed Synchronization in Go?. For more information, please follow other related articles on the PHP Chinese website!