场景
Avito是一名校车司机,他帮助4个Gopher孩子上学。每天,Avito在他们的社区等待孩子们。他不知道孩子们需要多长时间,但他确切地知道有4个孩子他需要等待。
当一个孩子准备好时,他/她会说:Done()
,将计数器减1。Avito仍然被阻塞,因为计数器仍然大于0。他必须等到所有其他孩子准备好。
如果有两个孩子同时准备好,它们的同时准备会导致WaitGroup
出现不一致吗?绝对不会。与sync
包中的大多数其他组件一样,WaitGroup
具有内置的同步机制,以处理并发。因此,计数器减少了准备好的孩子数量。
在最后一个孩子准备好后,Avito启动引擎,将他们送到学校。
就是这样!正如我所说,sync.WaitGroup
很简单。
超时
如果一个孩子花费太多时间准备,他们会不会因此迟到?如果Avito在时间到达时不管怎样都开始行驶会更好吗?嗯,Golang倾向于保持一切尽可能简洁,因此与其他编程语言中的CountDownLatch
(例如Java中的)不同,sync.WaitGroup
默认情况下不支持超时。在这种情况下,选择语句可能会有所帮助。
func main() {
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
defer wg.Done()
time.Sleep(5 * time.Second)
}()
done := make(chan bool)
go func() {
wg.Wait()
close(done)
}()
select {
case <-done:
log.Println(\\\"All done\\\")
case <-time.After(1 * time.Second):
log.Println(\\\"Hit timeout\\\")
}
}
孩子等待
在上面的示例中,Avito(主Goroutine)等待孩子(子Goroutines)。当我们希望子Goroutines等待主Goroutine时,WaitGroup
也可以使用。想象一下孩子们正在进行体育课。Torcher – 体育老师,在学生中主持比赛。他向WaitGroup
中Add(1)
,并要求所有孩子在相同的WaitGroup
上Wait()
。
当Torcher调用wg.Done()
时,计数器变为0,允许所有孩子同时开始奔跑。
展示你的代码!
package main
import (
\\\"log\\\"
\\\"sync\\\"
\\\"time\\\"
)
func main() {
kids := []string{\\\"Partier\\\", \\\"Stringer\\\", \\\"Candier\\\", \\\"Swimmer\\\"}
wg := sync.WaitGroup{}
wg.Add(len(kids))
for _, kid := range kids {
go func(name string) {
defer wg.Done()
prepare(name)
}(kid)
}
log.Printf(\\\"Avito: I\\\'m waiting for %d kids\\\\n\\\", len(kids))
wg.Wait()
log.Println(\\\"Avito: The kids are all ready, go!\\\")
}
func prepare(name string) {
log.Printf(\\\"%v: I\\\'m preparing for school\\\\n\\\", name)
time.Sleep(2 * time.Second)
log.Printf(\\\"%v: I\\\'m ready\\\\n\\\", name)
}
原创文章,作者:小技术君,如若转载,请注明出处:https://www.sudun.com/ask/33916.html