【问题标题】:Will time.Tick cause memory leak when I never need to stop it?当我从不需要停止 time.Tick 时,它会导致内存泄漏吗?
【发布时间】:2021-09-18 05:29:39
【问题描述】:

考虑以下代码:

go func() {
    for now := range time.Tick(time.Minute) {
        fmt.Println(now, statusUpdate())
    }
}()

我需要 for 循环永远运行并且永远不需要停止它。 这会导致内存泄漏吗?

我知道如果我需要打破 for 循环,它会导致内存泄漏。但是如果我不需要打破 for 循环呢?

医生说

虽然 Tick 对于不需要关闭 Ticker 的客户端很有用,但请注意,如果没有办法将其关闭,则垃圾收集器无法恢复底层 Ticker;它“泄漏”了。

我只是想把它做好。

【问题讨论】:

  • goroutine会一直运行,不会有内存泄漏
  • 另见 staticcheck 的 SA1015
  • 永远不会超出范围的东西无论如何都不会有资格进行 GC,因此它在逻辑上不会泄漏。
  • 当 go 例程发生恐慌时,这完全可能超出范围,尽管程序将立即以退出状态 2 终止。

标签: go


【解决方案1】:

首先,让我们看一下“内存泄漏”的定义,来自Wikipedia

在计算机科学中,内存泄漏是一种资源泄漏,当计算机程序以一种不再需要的内存没有释放的方式错误地管理内存分配时发生。

重要的是要注意,在您引用的文档中,它没有具体提到“内存泄漏”,只是“泄漏”(意思是“资源泄漏”)。有问题的资源不仅是ticker使用的内存,而且是运行它的goroutine。因此,我将把这个定义解释为更广泛地适用于“资源泄漏”。

正如您引用的文档所述,time.Tick 无法释放代码的资源。

因此,根据这个定义,如果在程序中的任何后续点都不再需要代码,那么就发生了资源泄漏。如果在创建后程序的其余部分总是需要代码,那么它不是泄漏。

然而,在 Wikipedia 的定义中,还有以下注释:

当对象存储在内存中但运行代码无法访问时,也可能发生内存泄漏。

同样,time.Tick 无法释放代码的资源。

所以根据这个继续定义,你可能会说time.Tick 的使用总是资源泄漏。

实际上,只要您range 超过time.Tick 而没有breaking,您就有合理的保证该代码将继续用于该程序的剩余部分,并且将有没有“泄漏”。如果您对代码是否会永远使用有任何疑问,请适当地使用time.NewTickerStop()

go func() {
    ticker := time.NewTicker(time.Minute)
    defer ticker.Stop()

    for now := range ticker.C {
        fmt.Println(now, statusUpdate())
        // some exception
        if (something) {
            break
        }
    }
}()

【讨论】:

    猜你喜欢
    • 2011-06-16
    • 1970-01-01
    • 2022-06-13
    • 2011-05-22
    • 2021-03-23
    • 2021-09-25
    • 2014-12-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多