//sync/waitgroup.go
func (wg *WaitGroup) Add(delta int) {
// statep状态(包含counter和waiter计数器),semap信号
statep, semap := wg.state()
// uint64(delta)<<32 获取counter计数器, 这里是counter + delta
state := atomic.AddUint64(statep, uint64(delta)<<32)
v := int32(state >> 32) // counter 计数器
w := uint32(state) // waiter 计数器
// counter 计数器 < 0 恐慌
if v < 0 {
panic("sync: negative WaitGroup counter")
}
//当 wait 和 add并发执行时,可能会发生恐慌。注意这里并不是说wait之后就不能添加Add了
if w != 0 && delta > 0 && v == int32(delta) {
panic("sync: WaitGroup misuse: Add called concurrently with Wait")
}
// add 完成
if v > 0 || w == 0 {
return
}
// This goroutine has set counter to 0 when waiters > 0.
// Now there can't be concurrent mutations of state:
// - Adds must not happen concurrently with Wait,
// - Wait does not increment waiters if it sees counter == 0.
// Still do a cheap sanity check to detect WaitGroup misuse.
if *statep != state {
panic("sync: WaitGroup misuse: Add called concurrently with Wait")
}
// Reset waiters count to 0.
*statep = 0 // 计数器置零
for ; w != 0; w-- {
runtime_Semrelease(semap, false) // 一个一个唤醒waiter
}
}