WaitGroup Insertion Placement for Goroutine Synchronization
In Go, the sync.WaitGroup type facilitates synchronization between goroutines by keeping track of the number of active goroutines and waiting until all goroutines have finished their execution before proceeding further. Proper placement of wg.Add() and wg.Done() calls is crucial for ensuring correct behavior.
Consider the following code:
<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>
In this example, wg.Add(1) is mistakenly placed within the anonymous function. This incorrect placement can lead to inconsistent values of v, often less than 100.
The reason for this discrepancy lies in the concurrency nature of goroutines. When placed within the goroutine, wg.Add(1) may run concurrently with wg.Done(), causing wg.Wait() to resume prematurely and underestimate the number of completed goroutines.
To address this issue, wg.Add(1) should be placed in the for loop before launching each goroutine:
<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>
This adjustment ensures that wg.Wait() will block until all wg.Done() calls have been made, allowing v to accurately reflect the number of completed goroutines.
In summary, always place wg.Add() before launching a goroutine and wg.Done() once the goroutine completes its execution to ensure proper synchronization and reliable result calculation.
The above is the detailed content of Where Should You Place `wg.Add()` and `wg.Done()` for Correct Goroutine Synchronization in Go?. For more information, please follow other related articles on the PHP Chinese website!