1. 问题现象

如果在开发过程中不考虑 goroutine 在什么时候能退出和控制 goroutine 生命期,就会造成 goroutine 失控或者泄露的情况 ,看示例代码:

func consumer(ch chan int) {for {data := <-chfmt.Println(data)}
}func main() {ch := make(chan int)for {var input string// 获取输入,模拟进程持续运行fmt.Scan(&input)go consumer(ch)// 输出现在的goroutine数量fmt.Println("goroutines 个数为:", runtime.NumGoroutine())}}

运行程序,每输入一个字符串+回车,将会创建一个 goroutine, 结果如下 :

a
goroutines 个数为: 2
b
goroutines 个数为: 3
c
goroutines 个数为: 4
d
goroutines 个数为: 5
e
goroutines 个数为: 6
f
goroutines 个数为: 7
g
goroutines 个数为: 8
h
goroutines 个数为: 9
i
goroutines 个数为: 10

上面代码模拟一个进程根据需要创建 goroutine 的情况 。我们发现, 随着输入的字符串越来越多, goroutine 将会无限制地被创建,但并不会结束,因为 consumer 是个阻塞操作,且 channel 中没有让其退出的操作。如果一直持续下去将会造成内存大量分配,最终使进程崩溃。

那要如何解决呢?

2. 解决方案

2.1 创建单个子协程,在子协程中处理业务

修改上面代码,将创建子协程的代码挪动到循环外面。

func consumer(ch chan int) {for {data := <-chfmt.Println("data is: ", data)}
}func main() {ch := make(chan int)go consumer(ch) // 在循环外面创建协程for {var input stringfmt.Scan(&input)fmt.Println("goroutines 个数为:", runtime.NumGoroutine())}}

这样输出结果为:

a
goroutines 个数为: 2
v
goroutines 个数为: 2
x
goroutines 个数为: 2
w
goroutines 个数为: 2
f
goroutines 个数为: 2
g
goroutines 个数为: 2
b
goroutines 个数为: 2

从结果可以看到协程数量并没有随着收入字符的增多而增加,但是存在一个问题就是,子协程并没有退出的机制。

如何解决呢?接着往下看

2.2 设置子协程退出条件

在主协程中设置当输入字符串为 quit 时,往通道里面写入 -1,子协程从通道里面获取数据为 -1 时就退出。此时主协程仍然是有效的,但是子协程会永远退出,所以协程数量为 1 。

func consumer(ch chan int) {for {data := <-ch// 收到的数据为 -1 时,退出该循环,同时也会退出该协程if data == -1 {break}fmt.Println("data is: ", data)}}func main() {ch := make(chan int)go consumer(ch) // 在循环外面创建协程for {var input stringfmt.Scan(&input)if input == "quit" {ch <- -1 // 当输入为 quit 时,往通道里面写入 -1}// 输出现在的goroutine数量fmt.Println("goroutines 个数为:", runtime.NumGoroutine())}
}

输出结果:

a
goroutines 个数为: 2
b
goroutines 个数为: 2
c
goroutines 个数为: 2
d
goroutines 个数为: 2
quit
goroutines 个数为: 2
a
goroutines 个数为: 1
b
goroutines 个数为: 1

3. 总结

从上面示例我们可以总结使用协程的一般原则:

  1. 尽量避免无限制的创建协程;
  2. 在需要反复创建协程的场景下,协程一定要有退出的条件,并且确保该退出条件能满足(即代码能执行到);

Go 知识点(11) — goroutine 泄露、设置子协程退出条件相关推荐

  1. golang中通知协程退出的方式

    1 需求分析 go语言中通知子 goroutine 退出的三种方式 方式1 通过全局变量:如果全局变量为真就退出 方式2 通过通道:协程在通道里面取到true就退出 方式3 通过context:通过调 ...

  2. golang协程退出

    主协程退出,子协程也跟着挂 func main() {go func() {i := 0for {i++fmt.Println("子 i = ", i)time.Sleep(tim ...

  3. 11.python之线程,协程,进程,

    一,进程与线程 1.什么是线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行 ...

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

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

  5. 开启协程_软件特攻队|GCC10发布,GCC 11将支持C++20协程功能?

    A coroutine is a function that can suspend execution to be resumed later. 协程是能暂停执行以在之后恢复的函数. 如上所述这是官 ...

  6. 使用waitgroup控制协程退出

    1.waitgroup三个接口特别重要 Add Done Wait 如下代码 import ("fmt""sync" )//如何解决主的grouptine在子协 ...

  7. 《快学 Go 语言》第 11 课 —— 千军万马跑协程

    协程和通道是 Go 语言作为并发编程语言最为重要的特色之一,初学者可以完全将协程理解为线程,但是用起来比线程更加简单,占用的资源也更少.通常在一个进程里启动上万个线程就已经不堪重负,但是 Go 语言允 ...

  8. Golang —— goroutine(协程)和channel(管道)

    协程(goroutine) 协程(goroutine)是Go中应用程序并发处理的部分,它可以进行高效的并发运算. 协程是轻量的,比线程更廉价.使用4K的栈内存就可以在内存中创建. 能够对栈进行分割,动 ...

  9. golang goroutine 协程原理

    一.goroutine简介 goroutine是go语言中最为NB的设计,也是其魅力所在,goroutine的本质是协程,是实现并行计算的核心.goroutine使用方式非常的简单,只需使用go关键字 ...

最新文章

  1. 数据库中间件MyCat学习总结(1)——MyCat入门简介
  2. BQ24296充电管理芯片使用过程中的注意事项
  3. 浅析神经协同过滤NCF在推荐系统的应用
  4. poj3671Dining Cows(DP)
  5. android后台截屏实现(3)--编译screencap
  6. TMS320F28335时钟(1)
  7. Web安全实践(13)嗅探,arp欺骗,会话劫持与重放攻击(上)
  8. 推荐算法的先验算法的连接_数据挖掘专注于先验算法
  9. bat批处理执行python_.bat批处理添加Python任务
  10. python如何创建模块视频_Python | 如何创建模块(模块示例)?
  11. 算法分析与设计「一」枚举
  12. python按照每行输出八个_Python/PyCharm的每行输出
  13. ONVIFclient搜索设备获取rtsp地址开发笔记(精华篇)
  14. gradle 刷新打包的时候报错
  15. 关于jquery获取单选框value属性值为on的问题
  16. 复现IIS PUT任意上传漏洞(过程,步骤,说明)
  17. qrcode.js的识别解析二维码图片和生成二维码图片
  18. 条令考试小程序辅助器_小程序条令考试 微信小程序条令考试答题器
  19. 计算机英语中CISC的汉语意思是,CISC是什么意思_CISC在线翻译_读音_用法_例句_含义-查字典网...
  20. mysql数据库级监控及常用计数器解析

热门文章

  1. 2022-2028年中国FEP薄膜行业市场发展规模及市场分析预测报告
  2. 2022-2028年中国汽轮发电机行业市场深度分析及发展趋势分析报告
  3. 2022-2028年中国散热产业深度调研及投资前景预测报告(全卷)
  4. Python 笔试面试合集
  5. C/C++ 编程规范(01 )— 排版
  6. 为什么神经网络的激活函数必须使用线性函数?
  7. IntelliJ IDEA中用快捷键自动创建测试类
  8. shap_value
  9. Pycharm中一些不为人知的技巧pycharm技巧
  10. PyTorch的十七个损失函数