Go WaitGroup源码解析
结构体
type WaitGroup struct {
noCopy noCopy
state1 [3]uint32
}
其中state1代表三个字段:counter, waiter, sema
- counter:计数器,每次经过wg.Add(X)或者wg.Done()后的值
- waiter:调用wg.Wait()的数量,也就是等待者的数量
- sema:信号量,用于换醒Wait()函数
退出WaitGroup的条件
counter == 0
Add(n)
- 更新counter的值。
counter += n
- 判断当前
counter > 0 || waiter == 0
,满足条件,说明当前还有groutine没有执行完,直接返回。 - 走到这一步,说明
counter == 0 && waiter != 0
,说明groutine全部执行了Done()方法,换醒执行了wg.Wait()的协程,将state设置成0,返回。
Wait()
- 循环判断下面操作
- 判断
counter == 0
,如果为true,说明groutine已经全部执行了Done()方法,Wait Done。 - 此时
counter != 0
,说明需要阻塞当前协程的执行,执行下面的CAS判断 - CAS判断wg.state有没有被改变,没有则更新wg.state为1,当前协程进入sleep状态,等待信号量换醒。换醒后继续循环判断,此时counter==0,直接wait done。
- CAS判断wg.state有没有被改变,有则继续循环判断。继续判断counter
Done()
Done 的实现就是 Add. 只不过我们常规用法 wg.Add(1) 是加 1 ,wg.Done() 是减 1,即 wg.Done() 可以用 wg.Add(-1) 来代替。尽管我们知道 wg.Add 可以传递负数当 wg.Done 使用,但是还是别这么用。
来源:https://www.cnblogs.com/xiaofua/p/16138840.html
本站部分图文来源于网络,如有侵权请联系删除。