在 Golang 中,sync.WaitGroup 是一个非常有用的同步机制,用于等待一组协程完成它们的工作。通过 wg.Add(n) 可以设置需要等待的协程数量,wg.Done() 用于告诉 WaitGroup 一个任务已经完成,而 wg.Wait() 会阻塞并等待直到所有的任务都完成。

使用方法详解

package main

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

func main() {
    var wg sync.WaitGroup

    // 使用 wg.Add(2) 表示我们有 2 个协程需要等待完成
    wg.Add(2)

    // 启动第一个协程
    go func() {
        defer wg.Done() // 当这个协程完成时调用 Done()
        time.Sleep(1 * time.Second)
        fmt.Println("Task 1 finished")
    }()

    // 启动第二个协程
    go func() {
        defer wg.Done() // 当这个协程完成时调用 Done()
        time.Sleep(2 * time.Second)
        fmt.Println("Task 2 finished")
    }()

    // 在主协程中等待所有的任务完成
    wg.Wait()
    fmt.Println("All tasks finished")
}

代码运行解释:

  1. 创建 sync.WaitGroup 对象
  • 通过 var wg sync.WaitGroup 创建一个等待组对象。
  1. 设置需要等待的协程数量
  • wg.Add(2) 表示我们有 2 个需要等待的任务(协程)。每次 Add(n) 后,你需要确保 Done() 的调用次数和 Add() 相匹配,否则会导致程序永远不会停止等待或者 panic。
  1. 启动协程
  • 使用 go 关键字启动两个协程,并在协程中处理任务。
  1. 调用 wg.Done()
  • 每次协程完成任务后使用 wg.Done() 标记一个任务已完成。这会减少 WaitGroup 的计数。
  1. 阻塞直到完成
  • 在主协程中调用 wg.Wait()。这会阻塞主协程直到计数器归零(即所有任务完成)。

注意事项

  1. Add 和 Done 的配对
    确保 Add(n)Done() 调用次数是严格配对的。如果协程不正确调用 Done(),进程就会一直被阻塞在 Wait()
  2. Add 要在启动协程之前调用
  • 如果 wg.Add(n) 写在 go 关键字的调用之后,你可能会出现竞态条件的问题,因为协程可能已经调用了 Done() 导致计数器减到了非预期的值。
  1. defer 的使用
  • 在协程内部使用 defer wg.Done() 是一个常见的写法,可以确保即使协程内部出现异常,Done() 也会被调用。

实践意义

sync.WaitGroup 可以帮助我们管理多协程并发,这在处理并行任务时非常有用,例如:

  • 并发下载文件或处理数据块。
  • 并行计算的完成后,再进行下一步的操作。


在Golang中sync.WaitGroup的使用方法插图

关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台

除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接

本文链接:http://www.choupangxia.com/2025/08/02/golang-sync-waitgroup/