goroutine泄露
目录
一.怎么避免goroutine泄露问题?
二.排查goroutine泄露
三.参考资源:
一.怎么避免goroutine泄露问题?
func main() {//协程泄露的问题//产生泄露问题的demo如下//一.goroutine+channel结合1.发送不接受(接受不完全)//for i := 0; i < 4; i++ {// queryAll()// fmt.Printf("接受的数:%d \n,", runtime.NumGoroutine())// //最后输出的 goroutines 数量是在不断增加的,每次多 2 个。也就是每调用一次,都会泄露 Goroutine。// //NumGoroutine 获取当前运行中的 goroutine 数量粗略估计。如果 goroutine 随着时间增加,数量在不断上升,而基本没有下降,基本可以确定存在泄露。// //这里的泄露在于 queryAll每次都会往channel发送三个数,但接受端并没有接受完全(仅接受了一个ch),所以产生泄露//}2.接受不发送//defer func() {// fmt.Printf("已存在的goroutines:%d\n", runtime.NumGoroutine())//}()//var ch chan struct{}//func() {// ch <- struct{}{}//}()//time.Sleep(time.Second)这个就是channel接受了值,但并没有发送,也会产生阻塞在业务场景中,许多业务逻辑里,基本只要有一个channel读写出现问题都会发生阻塞3.nil channel//defer func() {// fmt.Printf("已存在的goroutines:%d\n", runtime.NumGoroutine()) // 获取当前运行中的 goroutine 数量粗略估计,////}()//var ch chan int//func() {// ch <- 1//}()//fmt.Println(<-ch)//time.Sleep(time.Second)这个demo在于没有进行初始化channel,所以无论是读或者写这个通道都是不可用的3.1正确初始化方式如下//ch := make(chan int)//go func() {// ch <- 0//}()//go func() {// ch <- 1//}()//fmt.Println(<-ch)//time.Sleep(time.Second)二.奇怪的慢等待////for {// go func() {// _, err := http.Get("https://www.baidu.com/")// if err != nil {// fmt.Printf("http.Get err: %v\n", err)// }// // do something...//// }()//// time.Sleep(time.Second * 1)// fmt.Println("goroutines: ", runtime.NumGoroutine())//}这个奇怪的慢等待demo 展示了Go语言中比肩常见的经典场景,也就是一般应用程序访问第三方接口时,而第三方接口迟迟不返回响应结果,刚好Go语言中的http.Client没有设置超时时间,因此会导致阻塞导致goroutine暴涨,导致不断泄露,最后导致事故。三.互斥锁忘记解锁//total := 0//defer func() {// time.Sleep(time.Second)// fmt.Printf("total:%d\n", total)// fmt.Printf("当前正在运行的goroutine数量:%d\n", runtime.NumGoroutine())//}()//var mutex sync.Mutex//for i := 0; i < 10; i++ {// func() {// mutex.Lock()// defer mutex.Unlock() //在使用sync.Mutex互斥锁时时这里Unlock需要注意// total++//// }()//}在这个例子中第一个互斥锁加锁了,但没有进行Unlock,因此导致后面的所有 sync.Mutex 想加锁,却因未释放又都阻塞住了,直接goroutine泄露导致死锁现象,正确应该在mutex.lock后加一个mutex.Unlock//四.同步锁使用不当defer func() {fmt.Println("goroutines: ", runtime.NumGoroutine())}()go handle(3)time.Sleep(time.Second)}func queryAll() int {ch := make(chan int)for i := 0; i < 3; i++ {go func() {ch <- queryOne()}()}return <-ch
}func queryOne() int {n := rand.Intn(10) //返回一个半开区间的随机整数,当n<=0,会发生panictime.Sleep(time.Duration(n) * time.Millisecond) //一个持续时间以int64纳秒计数表示两个瞬间之间的时间。这种表示方法将最大的可表示的持续时间限制在大约290年。return n
}func handle(v int) {错误用例//var wg sync.WaitGroup//wg.Add(5)//for i := 0; i < v; i++ {// fmt.Println("脑子进煎鱼了")// wg.Done()//}//wg.Wait()//在这个例子中,我们调用了同步编排 sync.WaitGroup,模拟了一遍我们会从外部传入循环遍历的控制变量。//但由于 wg.Add 的数量与 wg.Done 数量并不匹配,因此在调用 wg.Wait 方法后一直阻塞等待。var wg sync.WaitGroupfor i := 0; i < v; i++ {wg.Add(1)defer wg.Done()fmt.Println("脑子进煎鱼了")}wg.Wait()
}
二.排查goroutine泄露
主要用`runtime.NumGoroutine`或者`pprof`工具。`pprof`会返回所有带有堆栈跟踪的`goroutine`列表。
三.参考资源:
煎鱼------[跟读者聊 Goroutine 泄露的 N 种方法,真刺激!](https://blog.csdn.net/EDDYCJY/article/details/115535237)
goroutine泄露相关推荐
- Go 知识点(11) — goroutine 泄露、设置子协程退出条件
1. 问题现象 如果在开发过程中不考虑 goroutine 在什么时候能退出和控制 goroutine 生命期,就会造成 goroutine 失控或者泄露的情况 ,看示例代码: func consum ...
- golang使用pprof检查goroutine泄露
有一段时间,我们的推送服务socket占用很不正常,我们自己统计的同时在线就10w的用户,但是占用的socket竟然达到30w,然后查看goroutine的数量,发现已经60w+. 每个用户占用一个s ...
- go 开了多少个goroutine 怎么看_线上 Go 程序偶尔出现异常怎么办?这个思路可解决你的烦恼...
点击上方蓝色"Go语言中文网"关注我们,领全套Go资料,每天学习 Go 语言 Go 项目做的比较大(主要说代码多,参与人多)之后,可能会遇到类似下面这样的问题: 程序老是半夜崩,崩 ...
- 回答我,停止 Goroutine 有几种方法?
大家好,我是煎鱼. 协程(goroutine)作为 Go 语言的扛把子,经常在各种 Go 工程项目中频繁露面,甚至有人会为了用 goroutine 而强行用他. 在 Go 工程师的面试中,也绕不开他, ...
- 实战Go内存泄露【转】
最近解决了我们项目中的一个内存泄露问题,事实再次证明pprof是一个好工具,但掌握好工具的正确用法,才能发挥好工具的威力,不然就算你手里有屠龙刀,也成不了天下第一,本文就是带你用pprof定位内存泄露 ...
- Go内存溢出与内存泄露
https://www.cnblogs.com/sunsky303/p/11077030.html 一.内存泄露与内存溢出的区别 内存溢出(out of memory,简称OOM) 内存溢出是指程序在 ...
- Goroutine 并发调度模型深度解析之手撸一个高性能 goroutine 池
文章目录 1 前言 2 Goroutine & Scheduler 2.1 线程那些事儿 2.1.1 用户级线程模型 2.1.2 内核级线程模型 2.1.3 两级线程模型 2.2 G-P-M ...
- Goroutine并发调度模型深度解析之手撸一个协程池
Goroutine & Scheduler Goroutine,Go语言基于并发(并行)编程给出的自家的解决方案.goroutine是什么?通常goroutine会被当做coroutine(协 ...
- go程序设计语言第八章-goroutine和channel
go程序设计语言第八章-goroutine and channel 8.1 goroutines In Go, each concurrently executing activity is call ...
最新文章
- 能力差的程序员90%输在这点上!CTO:其实都是瞎努力!
- pandas使用date_range函数按照指定的频率(freq)和指定的个数(periods)生成dataframe的时间格式数据列、基于dataframe的日期数据列生成日期索引
- unity3d 随机生成地形之随机山脉
- 鬼子进村(洛谷 1503)
- [Ubuntu] apache .htaccess根据访问的域名指向不同的目录
- 气象统计 第八次实习 EOF分析
- Python下载及环境的安装
- Insecure Randomness引发对随机数生成器抵挡加密攻击的方法
- 【Cesium】加载互联网地图服务——高德地图
- iOS 上传ipa包成功找不到ITMS-90338: Non-public API usage
- sendgrid html text,使用SendGrid发送电子邮件
- ICPC 2018 焦作 C题 Supreme Command
- Filter过滤器链执行顺序
- position常用属性值
- 全志H616方案香橙派Zero2开发板Linux系统设置静态 IP 地址的方法
- 学习永不止步!誉天9月开班计划来啦!
- dnc无线服务器,DNC设备联网管理系统
- 霓虹灯颜色渐变flash素材
- 手机怎么断开电脑微信连接服务器,手机连到电脑经常断开怎么办
- 十种方式拼接Python字符串