在go源码的sync包下 waitgroup.go, 总共不到100行代码
结构体定义如下 :
WaitGroup结构体不能复制
再看下核心函数Add
state := atomic.AddUint64(statep, uint64(delta)<<32)
这行代码表示传入的delta入参,通过原子方法atomic.AddUnit64来累加
然后获取计数器的值v
计数器 v < 0 就报错,说明waitGroup的计数器counter不能为负数
如果v > 0 或者 w = 0 ,代表没有等待或者有读锁,不需要唤醒goroutine,
add操作完毕,直接返回
add方法的调用不能和wait并行
w > 0 ,代表有goroutine阻塞等待着,循环唤醒它们
+++++++++++++++++++++++++++++++++++++++++++++
Done函数相当于Add函数 执行入参为-1,分析同上
++++++++++++++++++++++++++++++++++++++++++++++++++++
再看最后的核心方法Wait
1.循环获取状态state,使用了原子方法atomic.LoadUint64
2.获取计数器的值v和等待的goroutine数量w
3.如果v==0,代表都执行完了,没必要等着了,直接return收工
4.增加等待的goroutine计数,使用原子方法atomic.CompareAndSwapUnit64
+++++++++++++++++++++++++++++++++++++++++