2020年开年一系列糟糕的事情,新冠肺炎的肆虐让这个高速发展的国家不得不放缓脚步,科比的离开让我至今不敢相信。。。
可以等待一组 Goroutine 的返回。主goroutine调用Add来设置要等待的goroutine的数量。然后每一个goroutines运行并在完成时调用Done。同时,可以使用Wait来阻塞,直到所有的goroutines完成。在首次使用后,不能复制WaitGroup。
结构
上代码:
1 | type WaitGroup struct { |
- noCopy — 保证sync.WaitGroup不会被开发者通过再赋值的方式拷贝。
- state1 — 存储着状态和信号量。用一个12字节来保存,其中对齐的8个字节作为状态,另外4个为sema(用于唤醒其他等待的goroutine)
WaitGroup对外暴露了3个方法:Add()、Wait()和Done()。
Add()
1 | func (wg *WaitGroup) Add(delta int) { |
dd将可能为负的delta添加到WaitGroup计数器。如果计数器变为零,所有在等待时被阻塞的goroutine都会被释放。如果计数器变为负数,则panic。当计数器为0时发生的带正增量的调用必须在等待之前发生。带有负增量的调用,或者当计数器大于0时开始的带有正增量的调用,可以在任何时候发生。添加的调用应该在创建goroutine或要等待的其他事件的语句之前执行。如果重用了一个WaitGroup来等待几个独立的事件集,则必须在所有之前的等待调用返回之后执行新的添加调用。
Wait()
1 | func (wg *WaitGroup) Wait() { |
Wait()方法会通过for循环一直阻塞,在runtime_Semacquire时进入睡眠,直至计数器归零。
Done()
1 | func (wg *WaitGroup) Done() { |
Done()对计数器减一。
state()
1 |
|
获取状态的方法中判断当前编译器是不是64位:64位会吧后8个字节作为sema,32位会把前8个字节作为sema。