• Go并发可视化解释 - sync.WaitGroup


    场景

    Avito是一名校车司机,他帮助4个Gopher孩子上学。每天,Avito在他们的社区等待孩子们。他不知道孩子们需要多长时间,但他确切地知道有4个孩子他需要等待。

    1f83d3a42168b86cb20f4a40bb2c46dd.png
    1*aZnEggopv4Tsbyyj3e5JFg.png

    当一个孩子准备好时,他/她会说:Done(),将计数器减1。Avito仍然被阻塞,因为计数器仍然大于0。他必须等到所有其他孩子准备好。

    58d79d0dae2e0697c1b55c127815dce0.png
    1*qouGWmMAqY2CDrzz5widhQ.png

    如果有两个孩子同时准备好,它们的同时准备会导致WaitGroup出现不一致吗?绝对不会。与sync包中的大多数其他组件一样,WaitGroup具有内置的同步机制,以处理并发。因此,计数器减少了准备好的孩子数量。

    165e096cd0a5945983a8bdc41594df20.png
    1*057bX4zo_LCzEkdzGyDYpA.png

    在最后一个孩子准备好后,Avito启动引擎,将他们送到学校。

    af2c92caf10e838b7f80e03b3812c797.png
    1*rjH8OR3t7QgUx-dO-Iszeg.png

    就是这样!正如我所说,sync.WaitGroup很简单。

    超时

    如果一个孩子花费太多时间准备,他们会不会因此迟到?如果Avito在时间到达时不管怎样都开始行驶会更好吗?嗯,Golang倾向于保持一切尽可能简洁,因此与其他编程语言中的CountDownLatch(例如Java中的)不同,sync.WaitGroup默认情况下不支持超时。在这种情况下,选择语句可能会有所帮助。

    1. func main() {
    2. wg := sync.WaitGroup{}
    3. wg.Add(1)
    4. go func() {
    5. defer wg.Done()
    6. time.Sleep(5 * time.Second)
    7. }()
    8. done := make(chan bool)
    9. go func() {
    10. wg.Wait()
    11. close(done)
    12. }()
    13. select {
    14. case <-done:
    15. log.Println("All done")
    16. case <-time.After(1 * time.Second):
    17. log.Println("Hit timeout")
    18. }
    19. }

    孩子等待

    在上面的示例中,Avito(主Goroutine)等待孩子(子Goroutines)。当我们希望子Goroutines等待主Goroutine时,WaitGroup也可以使用。想象一下孩子们正在进行体育课。Torcher - 体育老师,在学生中主持比赛。他向WaitGroupAdd(1),并要求所有孩子在相同的WaitGroupWait()

    7211eba3e3606da7ce01f8f0efcfd83d.png
    1*btDQK4QKsu1HkEpfJDa2EA.png

    当Torcher调用wg.Done()时,计数器变为0,允许所有孩子同时开始奔跑。

    759f0b500c2eba454a2a7eaf39a77aaa.png
    1*VkV3VlRTx5jxXhauBH0_Dg.png

    展示你的代码!

    1. package main
    2. import (
    3. "log"
    4. "sync"
    5. "time"
    6. )
    7. func main() {
    8. kids := []string{"Partier", "Stringer", "Candier", "Swimmer"}
    9. wg := sync.WaitGroup{}
    10. wg.Add(len(kids))
    11. for _, kid := range kids {
    12. go func(name string) {
    13. defer wg.Done()
    14. prepare(name)
    15. }(kid)
    16. }
    17. log.Printf("Avito: I'm waiting for %d kids\n", len(kids))
    18. wg.Wait()
    19. log.Println("Avito: The kids are all ready, go!")
    20. }
    21. func prepare(name string) {
    22. log.Printf("%v: I'm preparing for school\n", name)
    23. time.Sleep(2 * time.Second)
    24. log.Printf("%v: I'm ready\n", name)
    25. }
  • 相关阅读:
    huggingface镜像网站
    如何用webgl(three.js)搭建处理3D隧道、3D桥梁、3D物联网设备、3D高速公路、三维隧道桥梁设备监控-第十一课
    Pytorch-CNN-Mnist
    re学习(37)DASCTF 2023 & 0X401七月暑期挑战赛 controflow
    请解释Java中的Hibernate框架
    电子学会C++编程等级考试2023年05月(一级)真题解析
    研究研究 ES_OEMCONVERT 标志
    读transformer的笔记
    React环境搭建
    BL200OPC UA分布式IO系统接线方式
  • 原文地址:https://blog.csdn.net/weixin_37604985/article/details/133956552