Go并发可视化解释:sync.WaitGroup
创始人
2025-07-04 09:50:54
0

场景

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

1*aZnEggopv4Tsbyyj3e5JFg.png

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

1*qouGWmMAqY2CDrzz5widhQ.png

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

1*057bX4zo_LCzEkdzGyDYpA.png

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

1*rjH8OR3t7QgUx-dO-Iszeg.png

就是这样!正如我所说,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()。

1*btDQK4QKsu1HkEpfJDa2EA.png

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

1*VkV3VlRTx5jxXhauBH0_Dg.png

展示你的代码!

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)
}

相关内容

热门资讯

PHP新手之PHP入门 PHP是一种易于学习和使用的服务器端脚本语言。只需要很少的编程知识你就能使用PHP建立一个真正交互的...
网络中立的未来 网络中立性是什... 《牛津词典》中对“网络中立”的解释是“电信运营商应秉持的一种原则,即不考虑来源地提供所有内容和应用的...
各种千兆交换机的数据接口类型详... 千兆交换机有很多值得学习的地方,这里我们主要介绍各种千兆交换机的数据接口类型,作为局域网的主要连接设...
粉嫩如何诠释霸道 东芝M805... “霸道粉”是个什么玩意东芝M805拿过来的时候,笔者扑哧笑了,不是笑这款笔记本,而是笑这款产品的颜色...
什么是大数据安全 什么是大数据... 在《为什么需要大数据安全分析》一文中,我们已经阐述了一个重要观点,即:安全要素信息呈现出大数据的特征...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
全面诠释网络负载均衡 负载均衡的出现大大缓解了服务器的压力,更是有效的利用了资源,提高了效率。那么我们现在来说一下网络负载...
如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
30分钟搞定iOS自定义相机 最近公司的项目中用到了相机,由于不用系统的相机,UI给的相机切图,必须自定义才可以。就花时间简单研究...
Intel将Moblin社区控... 本周二,非营利机构Linux基金会宣布,他们将担负起Moblin社区的管理工作,而这之前,Mobli...