【问题标题】:Are goroutines garbage collected together with their channels?goroutine 的垃圾是否与它们的通道一起收集?
【发布时间】:2016-10-31 15:03:07
【问题描述】:

想象一下下面的代码:

func waitForOneOfTwoProcesses() {

    c := make(chan bool)
    go func() {
        time.Sleep(1 * time.Second)
        c<-true
    }()
    go func() {
        time.Sleep(2 * time.Second)
        c<-true
    }()
    <-c

}

这是否泄漏了一个通道和一个 goroutine 或者 Go 是否认识到 c 已经消失并且 goroutine 可以退出?

如果通道的缓冲区大小为 2,答案会有所不同吗?

【问题讨论】:

    标签: go channel goroutine


    【解决方案1】:

    如果通道没有缓冲,那么其中一个匿名函数将不会返回。程序泄露了一个 goroutine 和 channel。

    如果通道的缓冲区大小大于或等于 1,则两个匿名函数都将返回。 goroutines 和 channel 使用的资源将被回收。

    缓冲区大小为 1 足以防止泄漏。函数waitForOneOfTwoProcesses 接收发送到c 的值之一。发送到c 的第二个值被缓存在通道中(由 GC 收集)。

    另一种确保 goroutine 返回的方法是使用非阻塞发送。将c &lt;- true 行替换为:

     select {
     case c <- true:
     default:
     }
    

    【讨论】:

    • 所以写入通道阻塞,即使通道超出范围并且永远无法再次读取。我想知道这是一个错误还是一个功能。
    • 是的,即使没有接收者,发送也会阻塞。在此特定示例中,可以编写运行时来检测应用程序何时在通道上完成接收,但这不是运行时通常可以检测到的。
    • 请注意,还有一个“非阻塞发送”可用,它解决了这个确切的问题 - 您将通道上的缓冲区设置为 1,并且每个都将在没有阻塞的情况下发送。这里有更详细的描述:blog.golang.org/go-concurrency-patterns-timing-out-and
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-30
    • 1970-01-01
    • 2011-01-04
    • 1970-01-01
    • 2011-01-26
    • 2021-05-25
    相关资源
    最近更新 更多