【golang】sync.WaitGroup详解

一、前言


Go语言在设计上对同步(Synchronization,数据同步和线程同步)提供大量的支持,比如 goroutine和channel同步原语,库层面有

  
- sync:提供基本的同步原语(比如Mutex、RWMutex、Locker)和 工具类(Once、WaitGroup、Cond、Pool、Map)
- sync/atomic:提供变量的原子操作(基于硬件指令 compare-and-swap)

-- 引用自《Golang package sync 剖析(一): sync.Once》

上一期中,我们介绍了 sync.Once 如何保障 exactly once 语义,本期文章我们介绍 package sync 下的另一个工具类:sync.WaitGroup

二、为什么需要 WaitGroup

想象一个场景:我们有一个用户画像服务,当一个请求到来时,需要

  1. 从 request 里解析出 user_id 和 画像维度参数
  2. 根据 user_id 从 ABCDE 五个子服务(数据库服务、存储服务、rpc服务等)拉取不同维度的信息
  3. 将读取的信息进行整合,返回给调用方

假设 ABCDE 五个服务的响应时间 p99 是 20~50ms 之间。如果我们顺序调用 ABCDE 读取信息,不考虑数据整合消耗时间,服务端整体响应时间 p99 是:

sum(A, B, C, D, E) => [100ms, 250ms]

先不说业务上能不能接受,响应时间上显然有很大的优化空间。最直观的优化方向就是,取数逻辑的总时间消耗:

sum(A, B, C, D, E) -> max(A, B, C, D, E)

具体到 coding 上,我们需要并行调用 ABCDE 五个子服务,待调用全部返回以后,进行数据整合。如何保障全部返回呢?

此时,sync.WaitGroup 闪耀登场。

三、WaitGroup 用法

官方文档对 WaitGroup 的描述是:一个 WaitGroup 对象可以等待一组协程结束。使用方法是:

  1. main协程通过调用 wg.Add(delta int) 设置worker协程的个数,然后创建worker协程;
  2. worker协程执行结束以后,都要调用 wg.Done()
  3. main协程调用 wg.Wait() 且被block,直到所有worker协程全部执行结束后返回。

这里先看一个典型的例子:

// src/cmd/compile/internal/ssa/gen/main.go
func  main() {
  // 省略部分代码 ...
  var wg sync.WaitGroup
  for _, task := range tasks {
    task  := task
    wg.Add(1)
    go func() {
      task()
      wg.Done()
    }()
  }
  wg.Wait()
  // 省略部分代码...
}

这个例子具备了 WaitGroup 正确使用的大部分要素,包括:

查看完整版(【golang】sync.WaitGroup详解)


1 篇内容引用

去去

237 声望
46 粉丝
0 条评论
推荐阅读
【golang】nil的理解
当出现不等于nil的时候,说明出现某些错误了,需要我们对这个错误进行一些处理,而如果等于nil说明运行正常。那什么是nil呢?查一下词典可以知道,nil的意思是无,或者是零值。零值,zero value,是不是有点熟悉...

去去1002阅读 3.2k

「刷起来」Go必看的进阶面试题详解
逃逸分析是Go语言中的一项重要优化技术,可以帮助程序减少内存分配和垃圾回收的开销,从而提高程序的性能。下面是一道涉及逃逸分析的面试题及其详解。

王中阳Go4阅读 1.9k评论 1

封面图
初学后端,如何做好表结构设计?
这篇文章介绍了设计数据库表结构应该考虑的4个方面,还有优雅设计的6个原则,举了一个例子分享了我的设计思路,为了提高性能我们也要从多方面考虑缓存问题。

王中阳Go4阅读 1.7k评论 2

封面图
又一款眼前一亮的Linux终端工具!
今天给大家介绍一款最近发现的功能十分强大,颜值非常高的一款终端工具。这个神器我是在其他公众号文章上看到的,但他们都没把它的强大之处介绍明白,所以我自己体验一波后,再向大家分享自己的体验。

良许5阅读 1.8k

一分钟搞明白!快速掌握 Go WebAssembly
最近因为各种奇怪的原因,更多的接触到了 WebAssembly。虽然之前很多博客也翻过写过各种文章,但总感觉欠些味道。于是今天梳理了一版,和大家一起展开学习。

煎鱼4阅读 2.2k

面试官:请说一下如何优化结构体的性能?
使用内存对齐机制优化结构体性能,妙啊!前言之前分享过2篇结构体文章:10秒改struct性能直接提升15%,产品姐姐都夸我好棒 和 Go语言空结构体这3种妙用,你知道吗? 得到了大家的好评。这篇继续分享进阶内容:结...

王中阳Go4阅读 3.9k评论 2

封面图
go 协程操作map导致的数据竞争及解决方法
有个查询结果集的操作,无可避免的需要在循环获取数据,然后将结果集放到 map 中,这个操作在压测的时候,没出现问题,发布到生产环境之后,开始偶现 fatal error: concurrent map read and map write 错误,导致...

hxd_5阅读 847评论 4

去去

237 声望
46 粉丝
宣传栏