2017-02-13 68 views
1

我试图理解并发和够程,并有大约如下的实验代码几个问题:为什么这个golang程序会造成内存泄漏?

  1. 为什么会创建一个内存泄漏?我认为在goroutine结束时返回将允许与其关联的内存得到清理。
  2. 为什么我的循环几乎不会达到999?实际上,当我输出到一个文件并研究输出时,我注意到它很少打印两位数的整数;第一次打印“99”是第2461行,第一次打印“999”第6120行。这种行为对我来说是意想不到的,这显然意味着我不了解goroutine调度的情况。

免责声明:

小心运行下面的代码,它可以造成系统崩溃,如果你不几秒钟后停止它!

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) 
    } 
} 
+7

你复制'同步.WaitGroup';代之以传递一个指针。 –

+2

运行'go vet'会显示错误。 – JimB

+0

嗨@TimCooper,关于内存泄漏,你是对的!这确实确定了问题#1,但是在这种情况下,例程4运行的远远超过其他问题;当输出到一个.txt文件时,我可以看到第一次#1运行是线1640001.这对我来说没有多大意义。 – dpog

回答

2

感谢Tim库珀,JimB和Greg提出的宝贵意见。代码的更正版本将在下面发布以供参考。

两个修复均通过引用,其固定在所述内存泄漏WaitGroup通过,并且正确地传递Ñ到匿名的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) 
    } 
}