Golang WaitGroup源码解析

Go WaitGroup源码解析

结构体

type WaitGroup struct {
 noCopy noCopy
 state1 [3]uint32
}

其中state1代表三个字段:counter, waiter, sema

创新互联建站成立于2013年,先为南京等服务建站,南京等地企业,进行企业商务咨询服务。为南京企业网站制作PC+手机+微官网三网同步一站式服务解决您的所有建站问题。

  • counter:计数器,每次经过wg.Add(X)或者wg.Done()后的值
  • waiter:调用wg.Wait()的数量,也就是等待者的数量
  • sema:信号量,用于换醒Wait()函数

退出WaitGroup的条件

  • counter == 0

Add(n)

  1. 更新counter的值。counter += n
  2. 判断当前counter > 0 || waiter == 0,满足条件,说明当前还有groutine没有执行完,直接返回。
  3. 走到这一步,说明counter == 0 && waiter != 0,说明groutine全部执行了Done()方法,换醒执行了wg.Wait()的协程,将state设置成0,返回。

Wait()

  1. 循环判断下面操作
  2. 判断counter == 0,如果为true,说明groutine已经全部执行了Done()方法,Wait Done。
  3. 此时counter != 0,说明需要阻塞当前协程的执行,执行下面的CAS判断
  4. CAS判断wg.state有没有被改变,没有则更新wg.state为1,当前协程进入sleep状态,等待信号量换醒。换醒后继续循环判断,此时counter==0,直接wait done。
  5. CAS判断wg.state有没有被改变,则继续循环判断。继续判断counter

Done()

Done 的实现就是 Add. 只不过我们常规用法 wg.Add(1) 是加 1 ,wg.Done() 是减 1,即 wg.Done() 可以用 wg.Add(-1) 来代替。尽管我们知道 wg.Add 可以传递负数当 wg.Done 使用,但是还是别这么用。


当前名称:Golang WaitGroup源码解析
本文路径:http://hbruida.cn/article/dsoisch.html