goroutine模拟了线程级别的返场的能力,但它的执行需要主协程给机会。一般的作法用sleep,chan阻塞,看起来让人不爽,本文介绍sync.WaitGroup 类型结合 defer 的特性,给出优雅的解决方案。

缘起

下面这段代码众所周知不会打招呼

....

func main(){

go sayHi(){

fmt.Println("say hello......")

}()

fmt.Println("main groutine....")

}

等待

上述代码不会讲hello,在于主协程main无等待(阻塞),子协程sayHi没有露脸的机会。

为了让子协程sayHai上场,通常在主协程末了加这么一句,让它睡会儿

time.Sleep(1e9)

但想想不科学,如果子协程在它睡期间,没能完成任务,超时了,子协程仍然打不了招呼。又或者子协程完成了,主协程还在睡,岂不是主线程不作为?睡的时间多久怎样才合理...

通道

用通道可解决阻塞时间合理性质疑。

若启用了多个子协程,可以这样实现主协程等待子协程执行完毕并退出的:声明一个和子协程数量一致的通道数组,然后为每个子协程分配一个通道元素,在子协程执行完毕时向对应的通道发送数据;然后在主协程中,依次读取这些通道接收子协程发送的数据,只有所有通道都接收到数据才会退出主协程。

代码看起来像这样

chs := make([]chan int, 10)

for i := 0; i < 10; i++ {

chs[i] = make(chan int)

go add(1, i, chs[i])

}

for _, ch := range chs {

}

感觉这样的实现有点蹩脚,不够优雅,于是 sync.waitGroup 入场了

WaitGroup 类型

sync.WaitGroup 类型是并发安全的,提供了以下三个方法:

func (wg *WaitGroup) Add(delta int)

func (wg *WaitGroup) Done()

func (wg *WaitGroup) Wait()

Add:WaitGroup 类型有一个计数器,默认值是0,通常通过个方法来标记需要等待的子协程数量

Done:当某个子协程执行完毕后,可以通过 Done 方法标记已完成,常用 defer 语句来调用

Wait 阻塞当前协程,直到对应 WaitGroup 类型实例的计数器值归零

代码

至此,相信你已经明白了,可组合使用 sync.WaitGroup 类型提供的方法,来替代之前通道中等待子协程执行完毕。

优雅等待子协程执行完毕代码如下

package main

import (

"fmt"

"sync"

)

func add_num(a, b int, done func()) {

defer done()

c := a + b

fmt.Printf("%d + %d = %d\n", a, b, c)

}

func main() {

var wg sync.WaitGroup

wg.Add(10)

for i := 0; i < 10; i++ {

go add_num(i, 1, wg.Done)

}

wg.Wait()

}

让当前协程永久阻塞

其实runtime 运行时默认是只开启一个逻辑处理器,如果不想用通道,也不阻塞,可以考虑设置多个逻辑处理器。或者干脆用select让当前主协程永久阻塞, 像下面这样

package main

import "runtime"

func DoSomething() {

for {

// 做点什么...

runtime.Gosched() // 防止本协程霸占CPU不放

}

}

func main() {

go DoSomething()

go DoSomething()

select{}

}

本作品采用《CC 协议》,转载必须注明作者和本文链接

go 怎么等待所有的协程完成_优雅地等待子协程执行完毕相关推荐

  1. python携程使用_简单了解python gevent 协程使用及作用

    简介 没有切换开销.因为子程序切换不是线程切换,而是由程序自身控制,没有线程切换的开销,因此执行效率高, 不需要锁机制.因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断 ...

  2. 协程 进程_进程,线程,协程的关系

    对于很多WEB服务器的开发人员,编程前几年大多以实现业务代码为主,很少接触或者系统的学习服务器的进程,线程,协成的概念和应用,下面我就进程,线程,协成在Nginx服务器中的应用对比浅析: 关系图: 概 ...

  3. python进程线程协程区别_进程和线程、协程的区别

    现在多进程多线程已经是老生常谈了,协程也在最近几年流行起来.python中有协程库gevent,py web框架tornado中也用了gevent封装好的协程.本文主要介绍进程.线程和协程三者之间的区 ...

  4. python协程框架_[记录]python的简单协程框架(回调+时间循环+select)

    # -*- coding: utf-8 -*- # @Time : 2018/12/15 18:55 # @File : coroutine.py #一个简单的 Coroutine 框架 import ...

  5. R语言迹检验协整关系式_使用R语言进行协整关系检验

    协整检验是为了检验非平稳序列的因果关系,协整检验是解决伪回归为问题的重要方法.首先回归伪回归例子: 伪回归Spurious regression伪回归方程的拟合优度.显著性水平等指标都很好,但是其残差 ...

  6. go 怎么等待所有的协程完成_理解真实世界中 Go 的并发 BUG

    点击上方蓝色"Go语言中文网"关注,回复「电子书」领全套Go资料 有几个学生研究归纳了go编程中的并发bugs,发表了一篇(英文)论文:<Understanding Real ...

  7. 关于go在函数退出后子协程的退出问题

    关于go在函数退出后子协程的退出问题 该问题来源于自己在读fabric源码时,看到的一个测试代码,在一个函数中启用协程,然后该函数退出了,由于平常没有这样处理过,以及受原有c++函数域的影响,认为函数 ...

  8. Go 知识点(14) — Go 多协程(单个协程触发panic会导致其它所有协程挂掉,每个协程只能捕获到自己的 panic 不能捕获其它协程)

    在多协程并发环境下,我们常常会碰到以下两个问题.假设我们现在有 2 个协程,我们叫它们协程 A 和 B . [问题1]如果协程 A 发生了 panic ,协程 B 是否会因为协程 A 的 panic ...

  9. Go 知识点(01)— 主协程与子协程执行顺序

    下面代码的输出结果是什么? package mainimport ("fmt" )func main() {for i := 0; i < 10; i++ {go func( ...

最新文章

  1. SAP MM 盘点事务中的序列号
  2. 微信小程序code 换取 session_key
  3. Smart Paster...great tool to paste large strings into Vs.net
  4. 思科交换机ping得通 traceroute不通_网络中经常接触的Ping 一次性教你弄懂如何检测三层网络...
  5. Java 8快多少?
  6. Hbase Compaction 源码分析 - CompactSplitThread 线程池选择
  7. python黑白图片上色_百度AI攻略:黑白图像上色
  8. 程序开发学习和工作中常用工具——Doxygen和graphviz和HTML Help WorkShop以及 Easy CHM
  9. C++_OpenCV模板匹配
  10. Java、JSP公文流转系统
  11. c# 小票打印机打条形码_C# Code 128条形码打印的问题
  12. 公司邮箱域名可以定制吗?公司邮箱申请注册?公司邮箱登录入口?
  13. 5G 时代,优酷推出的帧享究竟是什么?
  14. 得到app文稿导出_得到app
  15. java电信计费项目,java毕业设计_springboot框架的电信计费
  16. 大整数加法基本思路和代码(C++实现)
  17. 如何评估 Web3 项目的价值?
  18. 芝诺数解|【二】风禾尽起,且住为佳——重庆租房
  19. Linux实时操作系统Xenomai的一小时半入门视频推荐
  20. 关于快消产品的一点小小认识

热门文章

  1. esxi中利用ovf模板迁虚拟机
  2. python可以写什么视觉特效_Python实现视觉特效:一行命令给头像自动戴上口罩的案例...
  3. 怎么快速学会计算机程序知识,零基础学电脑怎样才能学得快,自学电脑的基础知识分享...
  4. 使用谷歌Colab(Colaboratory)免费GPU训练自己的模型及谷歌网盘无限容量(Google drive)申请教程
  5. 校园市场应该怎样做,看看小米有什么新招式
  6. 如何通过API接口获取item_get_pro - 获得淘宝商品详情高级版
  7. java email bean_JavaWeb学习笔记-第四章JavaBean技术
  8. JAVA 将图片转换成pdf文件
  9. 第三方阿里云盘小白羊版v2发布!提前尝鲜!!!!
  10. 会议记录管理系统(4) - 会议记录添加模块