【问题标题】:Why does reading from a nil channel increase the number of Goroutines?为什么从 nil 通道读取会增加 Goroutine 的数量?
【发布时间】:2020-06-26 08:31:19
【问题描述】:

我正在阅读这篇博客 https://medium.com/golangspec/goroutine-leak-400063aef468,并调整了以下示例,说明由于从 nil 通道接收而导致的 goroutine 泄漏:

package main

import (
    "flag"
    "fmt"
    "runtime"
    "time"
)

var initChannel bool

func main() {
    flag.Parse()

    var ch chan int
    if initChannel {
        ch = make(chan int, 1)
        ch <- 1
    }
    go func(ch chan int) {
        <-ch
    }(ch)

    c := time.Tick(1 * time.Second)
    for range c {
        fmt.Printf("#goroutines: %d\n", runtime.NumGoroutine())
    }
}

func init() {
    flag.BoolVar(&initChannel, "init", false, "initialize channel")
}

我注意到如果我用initChannelfalse 运行它,goroutines 的数量是 2:

> go run main.go
#goroutines: 2
#goroutines: 2

而如果我使用true 运行它,则数字是 1:

> go run main.go --init
#goroutines: 1
#goroutines: 1

但是,我不太明白为什么会这样。我只看到一个 go 语句,所以我希望在任何一种情况下都只有一个 goroutine。为什么从 nil 通道读取时会有两个 goroutine?

【问题讨论】:

    标签: go memory-leaks channel goroutine


    【解决方案1】:

    当您的应用启动时,已经有一个运行 main() 函数的 goroutine。

    如果您不初始化 ch 频道,它将保持其 zero value 即频道的 nilSpec: Receive operator:

    nil 频道接收永远阻塞。

    详情见How does a non initialized channel behave?

    所以如果频道是nil,启动的goroutine永远不会结束。因此,您将拥有 2 个 goroutine:main goroutine 和您启动的那个。

    如果你用 1 个缓冲区初始化通道并在其上发送一个值,那么你还将在“短时间内”拥有 2 个 goroutine,但启动的 goroutine 可以从中接收一个值然后立即结束。所以会剩下一个 goroutine,main goroutine。

    【讨论】:

      猜你喜欢
      • 2021-12-05
      • 2015-12-08
      • 2022-01-02
      • 2019-11-18
      • 2020-05-24
      • 1970-01-01
      • 2018-03-03
      • 2021-06-27
      • 1970-01-01
      相关资源
      最近更新 更多