【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
?
想象一个场景:我们有一个用户画像服务,当一个请求到来时,需要
- 从 request 里解析出 user_id 和 画像维度参数
- 根据 user_id 从 ABCDE 五个子服务(数据库服务、存储服务、rpc服务等)拉取不同维度的信息
- 将读取的信息进行整合,返回给调用方
假设 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 对象可以等待一组协程结束
。使用方法是:
- main协程通过调用
wg.Add(delta int)
设置worker协程的个数,然后创建worker协程; - worker协程执行结束以后,都要调用
wg.Done()
; - 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 篇内容引用
推荐阅读
【golang】nil的理解
当出现不等于nil的时候,说明出现某些错误了,需要我们对这个错误进行一些处理,而如果等于nil说明运行正常。那什么是nil呢?查一下词典可以知道,nil的意思是无,或者是零值。零值,zero value,是不是有点熟悉...
去去1002阅读 3.1k
Golang 中 []byte 与 string 转换
string 类型和 []byte 类型是我们编程时最常使用到的数据结构。本文将探讨两者之间的转换方式,通过分析它们之间的内在联系来拨开迷雾。
机器铃砍菜刀赞 24阅读 58.4k评论 2
万字详解,吃透 MongoDB!
MongoDB 是一个基于 分布式文件存储 的开源 NoSQL 数据库系统,由 C++ 编写的。MongoDB 提供了 面向文档 的存储方式,操作起来比较简单和容易,支持“无模式”的数据建模,可以存储比较复杂的数据类型,是一款非常...
JavaGuide赞 8阅读 1.8k
数据结构与算法:二分查找
一、常见数据结构简单数据结构(必须理解和掌握)有序数据结构:栈、队列、链表。有序数据结构省空间(储存空间小)无序数据结构:集合、字典、散列表,无序数据结构省时间(读取时间快)复杂数据结构树、 堆图二...
白鲸鱼赞 9阅读 5.4k
PHP转Go实践:xjson解析神器「开源工具集」
我和劲仔都是PHP转Go,身边越来越多做PHP的朋友也逐渐在用Go进行重构,重构过程中,会发现php的json解析操作(系列化与反序列化)是真的香,弱类型语言的各种隐式类型转换,很大程度的减低了程序的复杂度。
王中阳Go赞 11阅读 2.8k评论 4
Git操作不规范,战友提刀来相见!
年终奖都没了,还要扣我绩效,门都没有,哈哈。这波骚Git操作我也是第一次用,担心闪了腰,所以不仅做了备份,也做了笔记,分享给大家。问题描述小A和我在同时开发一个功能模块,他在优化之前的代码逻辑,我在开...
王中阳Go赞 6阅读 2.9k评论 4
妙啊,空结构体还能这么用?Go语言的结构体看这篇就够了
本文详解了Go语言结构体的各个知识点,最后介绍了空结构体的3种妙用。希望对你有帮助。定义结构体,是一种自定义的数据类型,由多个数据类型组合而成。用于描述一类事物相关属性。定义方式: {代码...} 实例化结...
王中阳Go赞 6阅读 1.2k
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。