iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > GO >golang内存泄漏的原因是什么
  • 644
分享到

golang内存泄漏的原因是什么

2023-07-04 23:07:35 644人浏览 安东尼
摘要

这篇“golang内存泄漏的原因是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Golang内存泄漏的原因是什么”文章吧

这篇“golang内存泄漏的原因是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Golang内存泄漏的原因是什么”文章吧。

泄漏原因有:1、time.After()的使用,每次time.After(duration x)会产生NewTimer(),在duration x到期之前,新创建的timer不会被GC,到期之后才会GC;2、time.NewTicker资源未及时释放;3、select阻塞;4、channel阻塞;5、申请过多的goroutine、goroutine阻塞;6、slice引起的等。

golang容易导致内存泄漏的几种情况

1. 定时器使用不当

1.1 time.After()的使用

默认的time.After()是会有内存泄露问题的,因为每次time.After(duration x)会产生NewTimer(),在duration x到期之前,新创建的timer不会被GC,到期之后才会GC。

随着时间推移,尤其是duration x很大的话,会产生内存泄露的问题,应特别注意

for true {select {case <-time.After(time.Minute * 3):    // do something  default:time.Sleep(time.Duration(1) * time.Second)}}

为了保险起见,使用NewTimer()或者NewTicker()代替的方式主动释放资源

timer := time.NewTicker(time.Duration(2) * time.Second)defer timer.Stop()for true {select {case <-timer.C:// do somethingdefault:time.Sleep(time.Duration(1) * time.Second)}}

1.2 time.NewTicker资源未及时释放

在使用time.NewTicker时需要手动调用Stop()方法释放资源,否则将会造成永久性的内存泄漏

timer := time.NewTicker(time.Duration(2) * time.Second)// defer timer.Stop()for true {select {case <-timer.C:// do somethingdefault:time.Sleep(time.Duration(1) * time.Second)}}

2. select阻塞

使用select时如果有case没有覆盖完全的情况且没有default分支进行处理,最终会导致内存泄漏

2.1 导致goroutine阻塞的情况

func main() {    ch2 := make(chan int)    ch3 := make(chan int)    ch4 := make(chan int)    go Getdata("https://www.baidu.com",ch2)    go Getdata("Https://www.baidu.com",ch3)    go Getdata("https://www.baidu.com",ch4)    select{        case v:=<- ch2:            fmt.Println(v)        case v:=<- ch3:            fmt.Println(v)    }}

上述这种情况会阻塞在ch4的消费处导致内存泄漏

2.2 循环空转导致CPU暴涨

func main() {fmt.Println("main start")msgList := make(chan int, 100)go func() {for {select {case <-msgList:default: }}}()c := make(chan os.Signal, 1)signal.Notify(c, os.Interrupt, os.Kill)s := <-cfmt.Println("main exit.get signal:", s)}

上述for循环条件一旦命中default则会出现循环空转的情况,并最终导致CPU暴涨

3. channel阻塞

channel阻塞主要分为写阻塞和读阻塞两种情况

空channel

func channelTest() {  //声明未初始化的channel读写都会阻塞    var c chan int  //向channel中写数据    go func() {        c <- 1        fmt.Println("g1 send succeed")        time.Sleep(1 * time.Second)    }()  //从channel中读数据    go func() {        <-c        fmt.Println("g2 receive succeed")        time.Sleep(1 * time.Second)    }()    time.Sleep(10 * time.Second)}

写阻塞

  • 无缓冲channel的阻塞通常是写操作因为没有读而阻塞

func channelTest() {    var c = make(chan int)  //10个协程向channel中写数据    for i := 0; i < 10; i++ {        go func() {            <- c            fmt.Println("g1 receive succeed")            time.Sleep(1 * time.Second)        }()    }  //1个协程丛channel读数据    go func() {        c <- 1        fmt.Println("g2 send succeed")        time.Sleep(1 * time.Second)    }()  //会有写的9个协程阻塞得不到释放    time.Sleep(10 * time.Second)}

  • 有缓冲的channel因为缓冲区满了,写操作阻塞

func channelTest() {    var c = make(chan int, 8)  //10个协程向channel中写数据    for i := 0; i < 10; i++ {        go func() {            <- c            fmt.Println("g1 receive succeed")            time.Sleep(1 * time.Second)        }()    }  //1个协程丛channel读数据    go func() {        c <- 1        fmt.Println("g2 send succeed")        time.Sleep(1 * time.Second)    }()  //会有写的几个协程阻塞写不进去    time.Sleep(10 * time.Second)}

读阻塞

  • 期待从channel读数据,结果没有goroutine往进写数据

func channelTest() {   var c = make(chan int)  //1个协程向channel中写数据  go func() {    <- c    fmt.Println("g1 receive succeed")    time.Sleep(1 * time.Second)  }()  //10个协程丛channel读数据  for i := 0; i < 10; i++ {    go func() {        c <- 1        fmt.Println("g2 send succeed")        time.Sleep(1 * time.Second)    }()  }  //会有读的9个协程阻塞得不到释放  time.Sleep(10 * time.Second)}

4. goroutine导致的内存泄漏

4.1 申请过多的goroutine

例如在for循环中申请过多的goroutine来不及释放导致内存泄漏

4.2 goroutine阻塞
4.2.1 I/O问题

I/O连接未设置超时时间,导致goroutine一直在等待,代码会一直阻塞。

4.2.2 互斥锁未释放

goroutine无法获取到资源,导致goroutine阻塞

//协程拿到锁未释放,其他协程获取锁会阻塞func mutexTest() {    mutex := sync.Mutex{}    for i := 0; i < 10; i++ {        go func() {            mutex.Lock()            fmt.Printf("%d goroutine get mutex", i)      //模拟实际开发中的操作耗时            time.Sleep(100 * time.Millisecond)        }()    }    time.Sleep(10 * time.Second)}

4.2.3 死锁

当程序死锁时其他goroutine也会阻塞

func mutexTest() {    m1, m2 := sync.Mutex{}, sync.RWMutex{}  //g1得到锁1去获取锁2    go func() {        m1.Lock()        fmt.Println("g1 get m1")        time.Sleep(1 * time.Second)        m2.Lock()        fmt.Println("g1 get m2")    }()    //g2得到锁2去获取锁1    go func() {        m2.Lock()        fmt.Println("g2 get m2")        time.Sleep(1 * time.Second)        m1.Lock()        fmt.Println("g2 get m1")    }()  //其余协程获取锁都会失败    go func() {        m1.Lock()        fmt.Println("g3 get m1")    }()    time.Sleep(10 * time.Second)}

4.2.4 waitgroup使用不当

waitgroup的Add、Done和wait数量不匹配会导致wait一直在等待

5. slice 引起的内存泄漏

当两个slice 共享地址,其中一个为全局变量,另一个也无法被GC;

append slice 后一直使用,没有进行清理。

var a []int func test(b []int) {        a = b[:3]        return}

6. 数组的值传递

由于数组时Golang的基本数据类型,每个数组占用不通的内存空间,生命周期互不干扰,很难出现内存泄漏的情况,但是数组作为形参传输时,遵循的时值拷贝,如果函数被多个goroutine调用且数组过大时,则会导致内存使用激增。

//统计nums中target出现的次数func countTarget(nums [1000000]int, target int) int {    num := 0    for i := 0; i < len(nums) && nums[i] == target; i++ {        num++    }    return num}

因此对于大数组放在形参场景下通常使用切片或者指针进行传递,避免短时间的内存使用激增。

以上就是关于“golang内存泄漏的原因是什么”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注编程网GO频道。

您可能感兴趣的文档:

--结束END--

本文标题: golang内存泄漏的原因是什么

本文链接: https://www.lsjlt.com/news/348393.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • golang内存泄漏的原因是什么
    这篇“golang内存泄漏的原因是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“golang内存泄漏的原因是什么”文章吧...
    99+
    2023-07-04
  • golang内存泄漏的原因及解决方法是什么
    Golang中的内存泄漏是指程序中分配的内存没有被适时地释放,导致程序占用的内存逐渐增加,最终耗尽系统内存资源。内存泄漏的原因和解决...
    99+
    2023-10-20
    golang
  • GoLang内存泄漏原因排查详解
    目录背景临时性内存泄漏通道理解背景 Go 语言中有对应的Go 内存回收机制,在Go采用 并发三色标记清除  算法, 但是由于实际的过程中 发现会有一些内存泄漏的常见,内存泄...
    99+
    2022-12-15
    GoLang内存泄漏 Go内存泄漏
  • java内存泄漏和内存溢出的原因是什么
    Java内存泄漏和内存溢出的原因如下:1. 内存泄漏:内存泄漏指的是在程序运行过程中,无用的对象仍然被保持在内存中,导致内存占用不断...
    99+
    2023-08-26
    java
  • JavaScript中出现内存泄漏的原因是什么
    本篇文章给大家分享的是有关JavaScript中出现内存泄漏的原因是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。泄露方式在接下来的内容中...
    99+
    2022-10-19
  • JavaScript中的内存泄漏的原因
    目录前言内存泄漏的场景全局变量闭包DOM元素引用总结前言 JavaScript的内存泄漏指的是一些不再需要的对象仍然占用着内存,导致内存使用量持续增加,甚至造成浏览器崩溃或性能下降。...
    99+
    2023-05-18
    JavaScript 内存泄漏
  • java中内部类出现内存泄漏的原因是什么
    这篇文章给大家介绍java中内部类出现内存泄漏的原因是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Java是什么Java是一门面向对象编程语言,可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序...
    99+
    2023-06-14
  • android内存泄漏的原因及解决方法是什么
    Android内存泄漏的原因可能有以下几个:1. 长生命周期的对象持有短生命周期的引用:当一个长生命周期的对象持有了一个短生命周期对...
    99+
    2023-08-08
    android
  • 内存泄露的原因是什么
    这篇文章主要介绍“内存泄露的原因是什么”,在日常操作中,相信很多人在内存泄露的原因是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”内存泄露的原因是什么”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!Th...
    99+
    2023-06-16
  • javascript内存泄漏有哪些原因
    本篇内容介绍了“javascript内存泄漏有哪些原因”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! ...
    99+
    2022-10-19
  • python内存泄漏的原因有哪些
    Python内存泄漏的原因有以下几个:1. 循环引用:当两个或多个对象相互引用时,如果没有妥善地处理,可能会导致内存泄漏。垃圾回收器...
    99+
    2023-09-15
    python
  • Android内存泄漏的原因有哪些
    Android内存泄漏的原因有哪些,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。在Android开发中,最容易引发的内存泄漏问题的是Context。比如Activity的Con...
    99+
    2023-06-17
  • JVM内存泄露的原因是什么
    本篇内容介绍了“JVM内存泄露的原因是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1 OOM的现象之一今天介绍第一种Java heap...
    99+
    2023-06-02
  • golang内存泄漏怎么排查
    在 Go 语言中,内存泄漏通常是由于不正确地使用或管理指针和引用导致的。以下是一些排查内存泄漏的常用方法:1. 使用 go buil...
    99+
    2023-10-21
    golang
  • Android内存泄漏导致的原因有哪些
    这篇文章主要介绍“Android内存泄漏导致的原因有哪些”,在日常操作中,相信很多人在Android内存泄漏导致的原因有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Android内存泄漏导致的原因有哪些...
    99+
    2023-07-05
  • ThreadLocal导致JVM内存泄漏原因探究
    目录为什么要使用ThreadLocal使用ThreadLocal具体实现引发内存泄漏的原因为什么要使用ThreadLocal 在一整个业务逻辑流程中,为了在不同的地方或者不同的方法中...
    99+
    2023-05-16
    JVM内存泄漏 JVM ThreadLocal内存泄漏
  • android内存泄露的根本原因是什么
    Android内存泄漏的根本原因是因为对象在不再使用时未能被垃圾回收器正确地回收,导致内存持续占用和增加。这主要是因为以下几个常见情...
    99+
    2023-09-15
    android
  • Node.js中出现内存泄漏的原因有哪些
    本篇文章给大家分享的是有关Node.js中出现内存泄漏的原因有哪些,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。内存泄漏(Memory  Leak)指由于疏忽或错误造...
    99+
    2023-06-17
  • Android内存泄漏导致原因深入探究
    目录什么是内存泄露哪些操作会造成内存泄漏常见内存泄露问题1.资源性对象未关闭2.注册对象未注销3.非静态内部类的静态实例4.单例模式引起的内存泄露5.Handler临时性内存泄露6....
    99+
    2023-02-17
    Android内存泄漏原因 Android内存泄漏几种情况
  • JavaScript内存泄漏和内存溢出是什么
    本篇内容主要讲解“JavaScript内存泄漏和内存溢出是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JavaScript内存泄漏和内存溢出是什么”吧! ...
    99+
    2022-10-19
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作