typora/note/Go/Goroutine泄漏.md
2024-12-12 10:48:55 +08:00

2.0 KiB
Raw Blame History

泄漏的大多数原因

  • Goroutine 内正在进行 channel/mutex 等读写操作,但由于逻辑问题,某些情况下会被一直阻塞。
  • Goroutine 内的业务逻辑进入死循环,资源一直无法释放。
  • Goroutine 内的业务逻辑进入长时间等待,有不断新增的 Goroutine 进入等待

channel发送不接收

  • 开启多个goroutine写channel
  • 只读了部分的channel导致goroutine阻塞不会释放
package main

func main() {
    for i := 0; i < 4; i++ {
        queryAll()
        fmt.Printf("goroutines: %d\n", runtime.NumGoroutine())
    }
}

func queryAll() int {
    ch := make(chan int)
    for i := 0; i < 3; i++ {
        go func() { ch <- query() }()
    }
    // 开启多个channel只接收了一个
    return <-ch
}

func query() int {
    n := rand.Intn(100)
    time.Sleep(time.Duration(n) * time.Millisecond)
    return n
}

channel接收不发送

  • 只开启了接收但是没有goroutine去发送数据到channel
func main() {
    defer func() {
        fmt.Println("goroutines: ", runtime.NumGoroutine())
    }()

    var ch chan struct{}
    go func() {
        ch <- struct{}{}
    }()
    
    time.Sleep(time.Second)
}

nil channel 读写都会阻塞goroutine

ch := make(chan int)
go func() {
    <-ch
}()
ch <- 0
time.Sleep(time.Second)

请求三方接口没有设置超时等待

func main() {
    for {
        go func() {
            _, err := http.Get("https://www.xxx.com/")
            if err != nil {
                fmt.Printf("http.Get err: %v\n", err)
            }
            // do something...
    }()

    time.Sleep(time.Second * 1)
    fmt.Println("goroutines: ", runtime.NumGoroutine())
    }
}

互斥锁忘记解锁

  • 互斥锁上锁后,忘记解锁
  • 造成其他goroutine锁等待进而产生资源泄漏
  • defer lock.Unlock()

同步锁使用不当

  • sync.WaitGroup
  • Add的数量和Done的数量不一致
  • Wait方法一直阻塞