Home > Article > Backend Development > What are the causes of golang memory leaks?
The reasons for the leak are: 1. The use of time.After(). Each time.After(duration x) will generate NewTimer(). Before duration x expires, the newly created timer will not be GC , GC will only occur after expiration; 2. time.NewTicker resources are not released in time; 3. select blocking; 4. channel blocking; 5. applying for too many goroutines, goroutine blocking; 6. caused by slice, etc.
The operating environment of this tutorial: Windows 7 system, GO version 1.18, Dell G3 computer.
The default time.After() will have a memory leak problem, because each time.After(duration x) will generate NewTimer( ), the newly created timer will not be GCed before duration x expires, and will only be GCed after expiration.
As time goes by, especially if the duration The method actively releases resources. Please check the difference between the two by yourself or read my previous articles https://blog.csdn.net/weixin_38299404/article/details/119352884
for true { select { case <-time.After(time.Minute * 3): // do something default: time.Sleep(time.Duration(1) * time.Second) } }
timer := time.NewTicker(time.Duration(2) * time.Second) defer timer.Stop() for true { select { case <-timer.C: // do something default: time.Sleep(time.Duration(1) * time.Second) } }
timer := time.NewTicker(time.Duration(2) * time.Second) // defer timer.Stop() for true { select { case <-timer.C: // do something default: time.Sleep(time.Duration(1) * time.Second) } }The above situation will block the consumption of ch3 and cause memory leaks
func main() { ch1 := make(chan int) ch2 := make(chan int) ch3 := make(chan int) go Getdata("https://www.baidu.com",ch1) go Getdata("https://www.baidu.com",ch2) go Getdata("https://www.baidu.com",ch3) select{ case v:=<- ch1: fmt.Println(v) case v:=<- ch2: fmt.Println(v) } }Once the above for loop condition hits default, loop idling will occur, which will eventually lead to CPU surge
Empty channel
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 := <-c fmt.Println("main exit.get signal:", s) }
Write blocking
The blocking of unbuffered channel is usually that the write operation blocks because there is no read.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) }
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) }
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) }
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) }
//协程拿到锁未释放,其他协程获取锁会阻塞 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) }
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) }
var a []int func test(b []int) { a = b[:3] return }
Go video tutorial
、Programming teaching】
The above is the detailed content of What are the causes of golang memory leaks?. For more information, please follow other related articles on the PHP Chinese website!