写点什么

谈谈 Golang 的同步等待组

  • 2021 年 12 月 30 日
  • 本文字数:1403 字

    阅读完需:约 5 分钟

作者:ReganYue

来源:恒生LIGHT云社区


大家好,这里是努力变得优秀的 R 君,这次我们继续来进行 Golang 系列《让我们一起 Golang》,区块链系列内容明年会继续更新,共识算法已经基本完毕,如果不出意外,元旦那个星期就是介绍如何构建公链项目了,本次我们来了解 Golang 的同步等待组,这也是一个比较容易理解的知识点,我们来看一看吧!


我们现在开十条子协程,然后当十条子协程全部结束后,主协程立马结束。动动你的小脑袋,想一想应该怎么做?如果是一条子协程的话就很容易实现,当这条子协程结束时让主协程结束就行了。但是我们现在是 10 条,让任何一条子协程发布让主协程结束的命令都不行,因为你无法确定哪一条子协程是最后结束的。所以我们现在用上了等待组。


等待组是什么原理呢?创造一个子协程就登记一下,然后子协程干完活就将其除名,名单除干净了就结束主协程。


我们来看看等待组的有关示例:


func main() {    fmt.Println(time.Now())    var wg sync.WaitGroup    //起一个协程就加一    wg.Add(1)    go func() {        for i:=0;i<5;i++{            fmt.Println(i)            //相当于阻塞一秒,读到时间            <- time.After(time.Second)        }        fmt.Println(time.Now())        //活干完之后减一        wg.Done()
}()
wg.Add(1) go func() { var i int ticker := time.NewTicker(time.Second) for{ <- ticker.C i++ fmt.Println("秒表",i) if i>9 { break } } fmt.Println(time.Now()) wg.Done() }() //等待组阻塞等待至记录清零为止 wg.Wait() fmt.Println("END")}
复制代码


这段代码是建立一条协程就使用 wg.Add(1)给等待组加一,然后活干完之后就减一。


WaitGroup 等待一组 goroutine 完成。主 goroutine 调用 Add 来添加要等待的 goroutine 的数量。 然后每个 goroutine 运行并在完成时调用 Done。 同时,Wait 可用于阻塞,直到所有 goroutine 完成。


Add()方法是用来设置等待组中的计数器的值,我们可以理解每个等待组中都有一个计数器,这个计数器可以用来表示这个等待组中要执行的协程数量。如果计数器为零,那么表示被阻塞的协程都被释放了。


Done()方法就是当同步等待组中的某个协程执行完毕后,使同步等待组中的计数器数量减一。


这里一条协程 5 秒结束,另一条协程 10 秒结束,那按理来说应该是 10 秒结束,我们来看看运行结果吧!


2021-08-25 19:10:28.3511953 +0800 CST m=+0.01698940101秒表 12秒表 2秒表 33秒表 44秒表 52021-08-25 19:10:33.4452142 +0800 CST m=+5.111008301秒表 6秒表 7秒表 8秒表 9秒表 102021-08-25 19:10:38.4369656 +0800 CST m=+10.102759701END
复制代码


下面来谈谈几个需要注意的事项:


  1. 我们使用等待组时不可以在 wg.Add()中填入负数,不然会导致报错。报错结果如下:panic: sync: negative WaitGroup counter 这点需要注意。

  2. WaitGroup 对象不是一个引用类型****在通过函数传值时需要使用地址,需要通过指针传值,不然程序会出现死锁!




想向技术大佬们多多取经?开发中遇到的问题何处探讨?如何获取金融科技海量资源?


恒生LIGHT云社区,由恒生电子搭建的金融科技专业社区平台,分享实用技术干货、资源数据、金融科技行业趋势,拥抱所有金融开发者。


扫描下方小程序二维码,加入我们!



发布于: 刚刚
用户头像

还未添加个人签名 2018.11.07 加入

还未添加个人简介

评论

发布
暂无评论
谈谈Golang的同步等待组