使用 Select +Timer 时如何避免内存泄露?

这篇文章深入探讨了在 Go 中高效使用计时器,并提供了在与 select 语句结合使用的时候如何避免潜在的内存泄漏问题的方法。Let’s Go !

最常见的 Timer + Select 使用方式

package main

import (
  "fmt"
  "time"
)

func main() {
  ch := make(chan int)
  // Starting a goroutine
  go func() {
    for {
      select {
      case num := <-ch:
        fmt.Println("get num is ", num)
      case <-time.After(2 * time.Second):
        fmt.Println("time's up!!!")
      }
    }
  }()
  for i := 0; i < 5; i++ {
    ch <- i
    time.Sleep(1 * time.Second)
  }
}

Go 标准库文档[1]提到,每次调用 time.After 都会创建一个新的计时器。所以我们需要考虑到一个重要的问题。

底层的计时器在计时器被触发之前不会被垃圾收集器回收。

也就是说如果这些计时器没有达到设定的时间,它们就不会被垃圾收集。这可能导致内存泄漏,特别是在经常使用计时器的长时间运行的程序中。

Timer 的最佳实践

为了更有效地管理资源并避免内存泄漏,可以使用 time.NewTimer 和 timer.Reset。这种方法允许重用相同的计时器,减少资源消耗和潜在的内存泄漏风险。

下面是使用 time.NewTimer 改进的代码示例:

//1. Define a duration for the timer.
idleDuration := 5 * time.Minute
//2. Create a new timer with the specified duration.
idleDelay := time.NewTimer(idleDuration)
//3. Ensure the timer is stopped properly to avoid resource leaks.
defer idleDelay.Stop()
//4. Enter a loop to handle incoming messages or time-based events.
for {
  //5. Reset the timer to the specified duration at the beginning of each loop iteration.
  idleDelay.Reset(idleDuration)
  
  //6. Use select to wait on multiple channel operations.
  select {
  // Case to handle incoming messages.
  case s, ok := <-in:
    // Check if the channel is closed. If so, exit the loop.
    if !ok {
      return
    }
    // Process the received message `s`.
    // Add relevant code here to handle the message.
  // Case to handle a situation where the timer elapses.
  case <-idleDelay.C:
    // Increment the idle counter or handle the timeout event.
    // This is typically where you'd add code to handle a timeout scenario.
    idleCounter.Inc()
  // Case to handle cancellation or context expiration.
  case <-ctx.Done():
    // Exit the loop if the context is done.
    return
  }
}

通过这些注释我们了解了如何使用计时器和 select 语句在并发的 Go 程序中协同工作。

Conclusion

上述的例子展示了在 Go 的并发编程中如何正确使用和管理计时器。开发者必须遵循 Go 标准库的建议,这样才能够写出更高效、可靠的代码。

参考资料
[1]

pkg functions: https://pkg.go.dev/time#pkg-functions


原文始发于微信公众号(Go Official Blog):使用 Select +Timer 时如何避免内存泄露?

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/269888.html

(0)
李, 若俞的头像李, 若俞

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!