Home  >  Article  >  Backend Development  >  Why is the Placement of `wg.Add()` Crucial for Proper Synchronization in Go\'s `sync.WaitGroup`?

Why is the Placement of `wg.Add()` Crucial for Proper Synchronization in Go\'s `sync.WaitGroup`?

Linda Hamilton
Linda HamiltonOriginal
2024-10-30 01:49:02150browse

  Why is the Placement of `wg.Add()` Crucial for Proper Synchronization in Go's `sync.WaitGroup`?

Correcting wg.Add() Placement for WaitGroup Synchronization

In Go, the sync.WaitGroup type provides synchronization between goroutines. Its primary purpose is to enable the main goroutine to wait for a group of goroutines to complete their tasks. However, the placement of wg.Add() calls is crucial for ensuring proper synchronization.

In the incorrect example:

<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>

The wg.Add(1) call is placed inside the anonymous function, which is a mistake. This misguided placement can lead to a situation where wg.Wait() returns prematurely because wg.Add(1) is executed after wg.Done() within the same goroutine. As a result, v will not accurately reflect the number of completed tasks, and its value will likely be less than 100.

In the corrected example:

<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>

The wg.Add(1) call is now placed outside the anonymous function, ensuring that the main goroutine has invoked all 100 goroutines and registered their completion tasks with wg before calling wg.Wait(). This correct placement guarantees that wg.Wait() will block until all 100 goroutines have completed their tasks, resulting in an accurate value of v.

General Rules for Using sync.WaitGroup:

To ensure successful synchronization using sync.WaitGroup, follow these guidelines:

  • Always call wg.Add() in the main goroutine before starting a new goroutine.
  • It is recommended to call wg.Done() using the defer statement to ensure it is executed even in the event of a goroutine panic.
  • When passing a sync.WaitGroup to other functions (avoid using package-level variables), pass a pointer to it to prevent copying and ensure that all changes are made to the original sync.WaitGroup.

The above is the detailed content of Why is the Placement of `wg.Add()` Crucial for Proper Synchronization in Go\'s `sync.WaitGroup`?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn