登录
首页 >  Golang >  Go教程

Golang并发同步:Mutex与WaitGroup详解

时间:2026-03-20 17:51:42 499浏览 收藏

本文深入解析了 Go 语言中 sync 包两大核心并发同步工具——Mutex 与 WaitGroup 的正确用法与实战要点:Mutex 作为结构体字段配合 defer 解锁,确保共享数据的读写安全;WaitGroup 则通过 Add、Done 和 Wait 的严格时序协调 goroutine 生命周期,避免竞态与死锁。文章不仅剖析常见误用陷阱(如函数内定义锁、Add 时机错误),还展示了二者组合应对并发更新+汇总结果的典型场景,并对比了 channel、atomic 和 RWMutex 等更优替代方案,帮助开发者写出高效、健壮、符合 Go 并发哲学的代码。

如何在Golang中使用sync处理并发操作_使用Mutex和WaitGroup同步

在 Go 中处理并发时,sync 包是核心工具之一。它不靠语言层面的锁机制,而是提供轻量、明确、可组合的同步原语。其中 Mutex 用于保护共享数据不被多个 goroutine 同时修改,WaitGroup 用于等待一组 goroutine 完成。两者常配合使用,但职责分明:一个管“读写安全”,一个管“生命周期协调”。

用 Mutex 保护共享变量,避免竞态

sync.Mutex 是互斥锁,确保同一时刻只有一个 goroutine 能进入临界区。关键点是:锁必须作用于要保护的数据上,且加锁/解锁需成对出现(推荐用 defer mu.Unlock() 防止遗漏)。

常见错误是把锁定义在函数内(每次调用都是新锁),或忘记解锁导致死锁。正确做法是把 Mutex 作为结构体字段,与被保护数据放在一起:

type Counter struct {
    mu    sync.Mutex
    value int
}

func (c *Counter) Inc() {
    c.mu.Lock()
    defer c.mu.Unlock()
    c.value++
}

func (c *Counter) Value() int {
    c.mu.Lock()
    defer c.mu.Unlock()
    return c.value
}

用 WaitGroup 等待多个 goroutine 结束

sync.WaitGroup 不是用来保护数据的,而是用来“计数 + 阻塞等待”。它有三个方法:Add(n) 增加计数,Done() 减一(通常 defer 调用),Wait() 阻塞直到计数归零。

注意:Add 必须在启动 goroutine 之前调用,否则可能 Wait 已返回而 goroutine 还没开始;Done 必须和 Add 匹配,否则会 panic 或永远阻塞。

典型用法:

var wg sync.WaitGroup
for i := 0; i 

Mutex 和 WaitGroup 组合使用的典型场景

当多个 goroutine 并发更新共享状态,并需要等它们全部完成后再读取结果时,就该一起用:

  • 初始化一个 WaitGroup 和带 Mutex 的结果容器(如 map 或 struct)
  • 每个 goroutine 执行任务后,用 Mutex 安全地更新结果,再调用 Done()
  • 主 goroutine 调用 Wait() 后,再用 Mutex 安全读取最终结果

例如批量请求 API 并汇总响应码:

type Result struct {
    mu     sync.Mutex
    codes  map[int]int
}

func (r *Result) Add(code int) {
    r.mu.Lock()
    defer r.mu.Unlock()
    r.codes[code]++
}

// ... 启动多个 goroutine 调用 r.Add(statusCode),最后 wg.Wait()

替代方案与注意事项

不是所有并发都需要 Mutex。优先考虑无锁方式:

  • channel 传递数据而非共享内存(Go 的哲学)
  • 对简单计数,可用 sync/atomic(如 atomic.AddInt64
  • RWMutex 适合读多写少场景,允许多个读、单个写

WaitGroup 不能重复使用(重置需用 sync.Pool 或新建),也不支持超时——如需等待带超时,应改用 context.WithTimeout + select

终于介绍完啦!小伙伴们,这篇关于《Golang并发同步:Mutex与WaitGroup详解》的介绍应该让你收获多多了吧!欢迎大家收藏或分享给更多需要学习的朋友吧~golang学习网公众号也会发布Golang相关知识,快来关注吧!

资料下载
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>