`sync.WaitGroup` 是 Go 语言中用于等待一组 goroutine 完成的结构。它通过计数器来跟踪正在执行的 goroutine 数量,并在计数器归零时解除阻塞。
### 概念
– **计数器**:`WaitGroup` 内部维护一个计数器,表示待完成的 goroutine 数量。
– **Add(delta int)**:增加或减少计数器的值,`delta` 为正数时增加,为负数时减少。
– **Done()**:将计数器减 1,通常在每个 goroutine 完成时调用。
– **Wait()**:阻塞当前 goroutine,直到计数器归零。
### 使用方法
1. **创建 `WaitGroup`**:声明一个 `sync.WaitGroup` 变量。
2. **增加计数器**:使用 `Add` 方法设置需要等待的 goroutine 数量。
3. **启动 goroutine**:在 goroutine 中执行任务,并在任务完成后调用 `Done`。
4. **等待完成**:在主 goroutine 中调用 `Wait`,等待所有 goroutine 完成。
### 示例代码
package main import ( "fmt" "sync" "time" ) func worker(id int, wg *sync.WaitGroup) { defer wg.Done() // 确保 goroutine 完成时调用 Done fmt.Printf("Worker %d starting\n", id) time.Sleep(time.Second) // 模拟任务 fmt.Printf("Worker %d done\n", id) } func main() { var wg sync.WaitGroup for i := 1; i <= 3; i++ { wg.Add(1) // 每启动一个 goroutine,计数器加 1 go worker(i, &wg) } wg.Wait() // 等待所有 goroutine 完成 fmt.Println("All workers done") }
### 输出
“`
Worker 1 starting
Worker 2 starting
Worker 3 starting
Worker 1 done
Worker 2 done
Worker 3 done
All workers done
“`
### 关键点
– **`Add` 调用时机**:应在启动 goroutine 前调用 `Add`,确保计数器正确。
– **`Done` 调用**:每个 goroutine 结束时必须调用 `Done`,通常使用 `defer` 确保执行。
– **`Wait` 调用**:主 goroutine 调用 `Wait` 以等待所有任务完成。
通过这些步骤,`sync.WaitGroup` 能有效管理多个 goroutine 的同步。