为什么这个golang程序会造成内存泄漏?

时间:2017-02-13 19:51:03

标签: go memory-leaks concurrency

我正在尝试理解并发性和goroutines,并对以下实验代码提出了几个问题:

  1. 为什么会造成内存泄漏?我认为在goroutine结束时返回会让与之相关的记忆得到清理。
  2. 为什么我的循环几乎不会达到999?事实上,当我输出到文件并研究输出时,我注意到它很少以两位数打印整数;第一次打印“99”是2461行,而“999”行6120.这种行为对我来说意外,这显然意味着我并不真正了解goroutine调度的情况。
  3. 免责声明:

    小心运行下面的代码,如果几秒钟后没有停止,可能会导致系统崩溃!

    CODE

    package main
    
    import (
        "fmt"
        "sync"
    )
    
    func main() {
      var wg sync.WaitGroup
        for {
          // spawn four worker goroutines
          spawnWorkers(4, wg)
          // wait for the workers to finish
          wg.Wait()
        }
    }
    
    func spawnWorkers(max int, wg sync.WaitGroup) {
      for n := 0; n < max; n++ {
            wg.Add(1)
            go func() {
                defer wg.Done()
                f(n)
              return
            }()
        }   
    }
    
    func f(n int) {
        for i := 0; i < 1000; i++ {
          fmt.Println(n, ":", i)
        }
    }
    

1 个答案:

答案 0 :(得分:2)

感谢Tim Cooper,JimB和Greg的有益评论。代码的更正版本发布在下面以供参考。

这两个修复是通过引用传入 WaitGroup ,它修复了内存泄漏,并将 n 正确传递到匿名goroutine中,并且

package main

import (
    "fmt"
    "sync"
)

func main() {
  var wg sync.WaitGroup
    for {
      // spawn four worker goroutines
      spawnWorkers(4,&wg)
      // wait for the workers to finish
      wg.Wait()
    }
}

func spawnWorkers(max int, wg *sync.WaitGroup) {
  for n := 0; n < max; n++ {
        wg.Add(1)
        go func(n int) {
            defer wg.Done()
            f(n)
          return
        }(n)
    }   
}

func f(n int) {
    for i := 0; i < 1000; i++ {
      fmt.Println(n, ":", i)
    }
}