目录

一.怎么避免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泄露相关推荐

  1. Go 知识点(11) — goroutine 泄露、设置子协程退出条件

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

  2. golang使用pprof检查goroutine泄露

    有一段时间,我们的推送服务socket占用很不正常,我们自己统计的同时在线就10w的用户,但是占用的socket竟然达到30w,然后查看goroutine的数量,发现已经60w+. 每个用户占用一个s ...

  3. go 开了多少个goroutine 怎么看_线上 Go 程序偶尔出现异常怎么办?这个思路可解决你的烦恼...

    点击上方蓝色"Go语言中文网"关注我们,领全套Go资料,每天学习 Go 语言 Go 项目做的比较大(主要说代码多,参与人多)之后,可能会遇到类似下面这样的问题: 程序老是半夜崩,崩 ...

  4. 回答我,停止 Goroutine 有几种方法?

    大家好,我是煎鱼. 协程(goroutine)作为 Go 语言的扛把子,经常在各种 Go 工程项目中频繁露面,甚至有人会为了用 goroutine 而强行用他. 在 Go 工程师的面试中,也绕不开他, ...

  5. 实战Go内存泄露【转】

    最近解决了我们项目中的一个内存泄露问题,事实再次证明pprof是一个好工具,但掌握好工具的正确用法,才能发挥好工具的威力,不然就算你手里有屠龙刀,也成不了天下第一,本文就是带你用pprof定位内存泄露 ...

  6. Go内存溢出与内存泄露

    https://www.cnblogs.com/sunsky303/p/11077030.html 一.内存泄露与内存溢出的区别 内存溢出(out of memory,简称OOM) 内存溢出是指程序在 ...

  7. Goroutine 并发调度模型深度解析之手撸一个高性能 goroutine 池

    文章目录 1 前言 2 Goroutine & Scheduler 2.1 线程那些事儿 2.1.1 用户级线程模型 2.1.2 内核级线程模型 2.1.3 两级线程模型 2.2 G-P-M ...

  8. Goroutine并发调度模型深度解析之手撸一个协程池

    Goroutine & Scheduler Goroutine,Go语言基于并发(并行)编程给出的自家的解决方案.goroutine是什么?通常goroutine会被当做coroutine(协 ...

  9. go程序设计语言第八章-goroutine和channel

    go程序设计语言第八章-goroutine and channel 8.1 goroutines In Go, each concurrently executing activity is call ...

最新文章

  1. 能力差的程序员90%输在这点上!CTO:其实都是瞎努力!
  2. pandas使用date_range函数按照指定的频率(freq)和指定的个数(periods)生成dataframe的时间格式数据列、基于dataframe的日期数据列生成日期索引
  3. unity3d 随机生成地形之随机山脉
  4. 鬼子进村(洛谷 1503)
  5. [Ubuntu] apache .htaccess根据访问的域名指向不同的目录
  6. 气象统计 第八次实习 EOF分析
  7. Python下载及环境的安装
  8. Insecure Randomness引发对随机数生成器抵挡加密攻击的方法
  9. 【Cesium】加载互联网地图服务——高德地图
  10. iOS 上传ipa包成功找不到ITMS-90338: Non-public API usage
  11. sendgrid html text,使用SendGrid发送电子邮件
  12. ICPC 2018 焦作 C题 Supreme Command
  13. Filter过滤器链执行顺序
  14. position常用属性值
  15. 全志H616方案香橙派Zero2开发板Linux系统设置静态 IP 地址的方法
  16. 学习永不止步!誉天9月开班计划来啦!
  17. dnc无线服务器,DNC设备联网管理系统
  18. 霓虹灯颜色渐变flash素材
  19. 手机怎么断开电脑微信连接服务器,手机连到电脑经常断开怎么办
  20. 十种方式拼接Python字符串

热门文章

  1. 利用css 设计markdown 主题
  2. 如何快速以管理员身份运行cmd命令符窗口
  3. UART、RS232、RS485、IIC、SPI、CAN、CANFD、LIN、flexray、以太网等总线介绍
  4. 教你用最简单的方法做布丁动画
  5. js学习笔记(获取选中内容、缓动动画、动态设置元素属性)
  6. 遍历二叉树的四种方式和图解
  7. 1.3.19 网络端口地址转换 NAPT 配置
  8. plsql auto 常用语法
  9. Arduino 震动感应灯
  10. Linux2:Xshell连接虚拟机与Linux常见的基本命令