Golang WaitGroup 踩坑

在Go语言中,sync.WaitGroup(简称WaitGroup)是用于多goroutine同步的核心机制,但其使用需谨慎,否则可能导致程序卡顿、死锁或数据竞争等问题。以下是关键踩坑点及解决方案:

  1. ‌未启动单独goroutine导致主线程阻塞‌
    ‌问题‌:若WaitGroup未在goroutine内调用,主线程可能因等待子任务完成而阻塞。
    ‌解决方案‌:确保WaitGroup操作在独立goroutine中执行:
go 复制代码
var wg sync.WaitGroup
wg.Add(1)
go func() {
    defer wg.Done()
    // 子任务逻辑
}()
wg.Wait() // 主线程等待子任务完成
  1. ‌计数器操作顺序错误‌
    ‌问题‌:Add(n)应在goroutine启动前调用,否则可能导致Wait()提前返回。
    ‌解决方案‌:遵循Add() -> 启动goroutine -> Done()的顺序:
go 复制代码
wg.Add(1) // 增加计数器
go func() {
    defer wg.Done() // 任务结束时减少计数器
    // 任务逻辑
}()
  1. ‌闭包变量捕获问题‌
    ‌问题‌:从循环启动goroutine时,若闭包捕获循环变量(如for循环中的i),可能导致所有goroutine共享同一变量值。
    ‌解决方案‌:通过参数传递循环变量值:
go 复制代码
for i := 0; i < 5; i++ {
    wg.Add(1)
    go func(num int) { // 传递参数
        defer wg.Done()
        fmt.Println("Goroutine", num)
    }(i) // 传递当前i值
}
  1. ‌未正确传递指针导致计数器失效‌
    问题‌:将WaitGroup作为值传递给函数时,子函数操作的是副本,主函数计数器不变。
    解决方案‌:传递指针引用:
go 复制代码
func worker(wg *sync.WaitGroup) {
    defer wg.Done()
    // 任务逻辑
}
wg.Add(1)
worker(&wg) // 传递指针
  1. ‌未调用Done()导致死锁‌
    问题‌:若goroutine未调用Done(),计数器永远不会归零,Wait()将永久阻塞。
    解决方案‌:确保每个goroutine结束前调用Done():
go 复制代码
go func() {
    defer wg.Done() // 确保Done()在return前执行
    // 任务逻辑
}()
  1. ‌并发场景下的资源泄漏‌
    ‌问题‌:若WaitGroup未正确管理goroutine生命周期,可能导致资源泄漏。
    ‌解决方案‌:结合context实现超时控制:
go 复制代码
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
go func(ctx context.Context) {
    select {
    case <-ctx.Done():
        return // 超时退出
    case <-time.After(2 * time.Second):
        // 任务逻辑
    }
}(ctx)

示例代码

go 复制代码
var wg sync.WaitGroup
wg.Add(1)
go func() {
    defer wg.Done()
    time.Sleep(1 * time.Second)
    fmt.Println("Task completed")
}()
wg.Wait() // 等待任务完成

WaitGroup是Go并发编程的基石,但需严格遵循计数器操作顺序和闭包变量传递规则,避免常见陷阱。

相关推荐
CCPC不拿奖不改名几秒前
面向对象编程:继承与多态+面试习题
开发语言·数据结构·python·学习·面试·职场和发展
Awkwardx2 分钟前
MySQL数据库—MySQL复合查询
数据库·mysql
꧁Q༒ོγ꧂3 分钟前
算法详解(一)--算法系列开篇:什么是算法?
开发语言·c++·算法
2301_800256113 分钟前
R-Tree创建与遍历,R-Tree在4类空间查询中的应用,实现4类空间查询的各类算法[第8章]
数据库·算法·机器学习·postgresql·r-tree
十月南城3 分钟前
分布式ID选型——雪花、号段、数据库自增与时钟回拨的风险控制
数据库·分布式
老邓计算机毕设3 分钟前
SSM校园快递代取平台32618(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·ssm 框架·校园快递代取平台
论迹8 分钟前
【Redis】-- 单线程模型
数据库·redis·缓存
悦数图数据库9 分钟前
BOSS 直聘基于悦数图数据库构建智能根因定位平台的实践
数据库·人工智能
星火开发设计13 分钟前
Python数元组完全指南:从基础到实战
开发语言·windows·python·学习·知识·tuple
wuk99814 分钟前
栅格障碍物地图生成与机器人路径规划MATLAB程序
开发语言·matlab