Golang面试题:WaitGroup 实现原理

文摘   2025-02-01 13:36   四川  

Go 的并发模型讲究 Goroutine,轻量、高效。程序员只要一个 go 关键字,便能启动新 Goroutine。可启动容易,等它们全部结束难。想象一下,多个工人在干活,工头得等所有工人干完才能下班。WaitGroup 就是这个工头。

WaitGroup,顾名思义,“等待一组”。背后有三主要动作:AddDoneWait。怎么理解?我给你举个小例子。

老王是包工头,他派了几个工人(Goroutine)搬砖。首先是安排任务Add 就是安排任务数量。例如,今天有三车砖要搬,老王就告诉 WaitGroup:我们要搬三车,接着启动干活的人。

go


wg.Add(3)

这三个工人满怀干劲,各自奔向自己的砖车。而搬完之后,工人需要告诉老王,活儿干完了,Done 此时派上用场。每搬完一车砖,工人会喊一嗓子:我搞定了。这里不需要你传参数,Done 只做个减法,把欠的活儿数减一。

go


wg.Done() // 也可以写作 wg.Add(-1)

最后一个动作,Wait。你想想老王这个工头,派完了活儿,他就得等着。如果不等,工人还在搬砖,工头拍拍屁股走了,这批活就失控了。Wait 会阻塞老王的流程,阻止他提前收工。等所有工人干完活了,老王才能继续该干的事儿,比如结工钱、收工。

go


wg.Wait()

上面是 WaitGroup 基本的运用逻辑,底下呢? 哇,其实特别简单。

Go 的标准库中,WaitGroup 由三个核心字段支撑。counter、waiter 和 semaphore。别被专业词吓住,接着听。

  • counter
    :其实就是干活的量,你 Add 多少它记住,每 Done 一下它就减,到零了说明活儿完了。
  • waiter
    :像是等候室的计数器,Wait 一调用,表示“老王”进等候室了,直到 counter 归零,“老王”才能被放出来。
  • semaphore
    :不怎么起眼的小家伙,控制的是 Goroutine 之间信号的同步。譬如,有人在搬完砖后,会触发一个小信号通知“屋内”老王做检查。

你看这个简单的并发控制工具,调用时注意的是 race condition(竞争条件)。什么意思?假设多个工人(Goroutine)在修改同一个计数器,WaitGroup 帮你做了合适的同步。所有事都是并发安全的。程序员不用自己操心琐碎、复杂的多线程锁逻辑,少了很多负担。

特别提一点,使用 WaitGroup 要注意,别传值传递,要传指针。换句话说,WaitGroup 结构体传递必须谨慎,因为它背后有内在的状态管理。否则你等半天,工头没听见任何工人完成通知,直接走了,这也未必是好事。


粒粒快点跑
我是粒姐,11年老猎头,职业咨询顾问,曾创立两家猎头公司。 分享求职技巧和职场经验,职业愿景是帮助1000人找到心仪工作。 猎聘签约求职教练,1V1咨询,求职辅导,职业规划咨询,职场辅导。视频号:#粒粒快点跑
 最新文章