2017-02-13 10 views
1

私は並行性とゴルーチンを理解しようとすると、以下の実験的なコードについてのカップルの質問を持っていたのです:なぜこのゴランプログラムはメモリリークを引き起こしますか?

  1. なぜそれがメモリリークを作成するのですか?私は、ゴルーチンの終わりに戻ると、それに付随する記憶が整理されると考えました。
  2. なぜ私のループはほとんど999に達しませんか?実際、ファイルに出力して出力を調べると、2桁の数字を出力することはめったにありません。最初に "99"を出力するのは2461行、 "999"行は6120です。この動作は予期しないことです。これは明らかにgoroutineスケジューリングで何が起こっているのか分かりません。

免責事項:

あなたは数秒後に停止しない場合は、以下のコードを実行するように注意してください、それはあなたのシステムがクラッシュすることができます!彼らの有益なコメントをティム・クーパー、JimB、およびグレッグに

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を修正しますが、そのシナリオではgoroutine 4は他のものよりはるかに多く実行されます。 .txtファイルに出力すると、#1が最初に実行されるのが1640001行であることがわかります。それは私にはあまり意味がありません。 – dpog

答えて

2

感謝。修正されたコードのバージョンは、参照のために以下に掲載されています。

2つの修正は、あなたが `同期をコピーしているメモリリークを固定された基準によってWaitGroupに合格すると、匿名のゴルーチンに正しくNを渡すために、そして

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) 
    } 
} 
関連する問題