其他
Go语言核心手册-8.sync.WaitGroup
func coordinateWithChan() {
sign := make(chan struct{}, 2)
num := int32(0)
fmt.Printf("The number: %d [with chan struct{}]\n", num)
max := int32(10)
go addNum(&num, 1, max, func() {
sign <- struct{}{}
})
go addNum(&num, 2, max, func() {
sign <- struct{}{}
})
<-sign
<-sign
}
func coordinateWithWaitGroup() {
var wg sync.WaitGroup
wg.Add(2) // 计数器加2
num := int32(0)
fmt.Printf("The number: %d [with sync.WaitGroup]\n", num)
max := int32(10)
go addNum(&num, 3, max, wg.Done) // 计数器减1
go addNum(&num, 4, max, wg.Done) // 计数器减1
wg.Wait() // 会阻塞,直到计数器值为0,然后就会被唤醒
}
坑1(计数器为负数):sync.WaitGroup类型值中计数器的值如果小于0,会直接抛出Panic。
坑2(同时调用Add和Wait):如果我们对它的Add方法的首次调用,与对它的Wait方法的调用是同时发起的,比如,在同时启用的两个 goroutine 中,分别调用这两个方法,那么就有可能会让这里的Add方法抛出一个 panic。
坑3(跨越计数周期):如果在一个此类值的Wait方法被执行期间,跨越了两个计数周期,那么就会引发一个 panic。
var (
wg sync.WaitGroup
succs []*NotifyMessage
fails []*NotifyMessage
)
for _, message := range t.PushMessages {
wg.Add(1) // 计数加1
go func(message mipush.PushMessage) {
defer func() {
wg.Done() // 计数减1
}()
// 发送IOS/Android/PC等渠道的Push
// 代码省略...
}(message)
}
wg.Wait() // 阻塞,直到计数器值为0,然后就会被唤醒
// 数据统计
SendNotify(t.ID, t.TotalPage, t.TaskPage, t.AppType, t.AppLocal, fails, succs)