go语言学习笔记32  WaitGroup源码分析_读锁

在go源码的sync包下 waitgroup.go, 总共不到100行代码

结构体定义如下

go语言学习笔记32  WaitGroup源码分析_代码结构_02

WaitGroup结构体不能复制

再看下核心函数Add

go语言学习笔记32  WaitGroup源码分析_代码结构_03

state := atomic.AddUint64(statep, uint64(delta)<<32)

这行代码表示传入的delta入参,通过原子方法atomic.AddUnit64来累加

然后获取计数器的值v

go语言学习笔记32  WaitGroup源码分析_读锁_04

计数器 v < 0 就报错,说明waitGroup的计数器counter不能为负数

如果v > 0 或者 w = 0 ,代表没有等待或者有读锁,不需要唤醒goroutine,

add操作完毕,直接返回

add方法的调用不能和wait并行

w > 0 ,代表有goroutine阻塞等待着,循环唤醒它们

+++++++++++++++++++++++++++++++++++++++++++++

go语言学习笔记32  WaitGroup源码分析_代码结构_05

Done函数相当于Add函数 执行入参为-1,分析同上

++++++++++++++++++++++++++++++++++++++++++++++++++++

再看最后的核心方法Wait

go语言学习笔记32  WaitGroup源码分析_读锁_06

1.循环获取状态state,使用了原子方法atomic.LoadUint64

2.获取计数器的值v和等待的goroutine数量w

3.如果v==0,代表都执行完了,没必要等着了,直接return收工

go语言学习笔记32  WaitGroup源码分析_读锁_07

4.增加等待的goroutine计数,使用原子方法atomic.CompareAndSwapUnit64

+++++++++++++++++++++++++++++++++++++++++

go语言学习笔记32  WaitGroup源码分析_代码结构_08

go语言学习笔记32  WaitGroup源码分析_代码结构_09

go语言学习笔记32  WaitGroup源码分析_读锁_10

go语言学习笔记32  WaitGroup源码分析_读锁_11

go语言学习笔记32  WaitGroup源码分析_读锁_12

go语言学习笔记32  WaitGroup源码分析_代码结构_13

go语言学习笔记32  WaitGroup源码分析_代码结构_14