GO:同步工具WaitGroup

什么是 WaitGroup?

WaitGroup 是 Go 的标准库 sync 包中提供的一种并发控制工具,用于等待一组 goroutine 完成工作。它非常适合在主线程需要等待一组 goroutine 全部完成时使用。


通俗解释

可以把 WaitGroup 想象成一个计数器:

  1. 启动任务时:给计数器加 1。
  2. 任务完成时:给计数器减 1。
  3. 等待所有任务完成时:程序会阻塞,直到计数器变为 0。

用生活中的例子理解:

  • 一个老师(主 goroutine)安排 3 个学生(goroutines)做作业。
  • 每个学生做完后告诉老师。
  • 老师会等所有学生都完成后才下班(主 goroutine 退出)。

基本用法

sync.WaitGroup 的主要方法:

  1. Add(delta int):增加或减少计数器值。
  2. Done():减少计数器值(等价于 Add(-1))。
  3. Wait():阻塞当前 goroutine,直到计数器变为 0。

示例代码:

package main

import (
	"fmt"
	"sync"
	"time"
)

func worker(id int, wg *sync.WaitGroup) {
	defer wg.Done() // 任务完成时调用 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

	// 启动 3 个 goroutine
	for i := 1; i <= 3; i++ {
		wg.Add(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

关键点解析

  1. wg.Add(1)
    每次启动一个 goroutine,计数器加 1。

  2. defer wg.Done()
    每个 goroutine 完成任务时,计数器减 1。

  3. wg.Wait()
    主 goroutine 阻塞,直到计数器变为 0,表示所有 goroutine 都完成了工作。


注意事项

  1. 必须匹配 AddDone
    每个 Add 对应一个 Done,否则程序会死锁。

  2. 调用顺序
    在调用 Wait() 之前,Add 的操作必须完成;否则可能导致意外行为。

  3. 避免重复使用
    一个 WaitGroup 实例只能用于一组任务,任务完成后不能重用。


总结

  • WaitGroup 是 Go 中用于管理并发任务的一种同步工具。
  • 通过计数器机制,可以确保主线程等待所有 goroutine 完成后再继续执行。
  • 它是 Go 并发编程中常用的基础工具之一。
posted @ 2024-12-18 12:44  牛马chen  阅读(11)  评论(0编辑  收藏  举报