9

簡単な例として、次のコードを検討してください。

func printer(c <-chan int) {
    for {
        fmt.Print(<-c)
    }
}

func provide() {
    c := make(chan int)

    go printer(c)

    for i := 1; i <= 100; i++ {
        c <- i
    }
}

この関数は、生成されたデータを出力provideする go ルーチンを作成します。printerprovide

私の質問は、空のチャネルでprovide戻ってブロックを開始した後に何が起こるかということです。printerこれ以上の参照がないため、go ルーチンはリークしますcか、それともガベージ コレクターがこのケースをキャッチして、go ルーチンと の両方を破棄しcますか?

この種のコードが実際にメモリ リークを引き起こす場合、そのようなメモリ リークの発生を防ぐためにどのような戦略を立てることができますか?

4

2 に答える 2

0

次のプログラムを試して、実際にメモリ リークが発生することを確認してください。このプログラムは RAM をすぐに食い尽くすことに注意してください。それを殺す準備をしてください。

package main

func worker(c <-chan int) {
    var i int

    for {
        i += <-c
    }
}

func wrapper() {
    c := make(chan int)

    go worker(c)

    for i := 0; i < 0xff; i++ {
        c <- i
    }
}

func main() {
    for {
        wrapper()
    }
}

リークを解決するには、孤立した go ルーチンによって参照されているチャネルを閉じます。ランタイムは、クローズされたチャネルのみからの Go ルーチンの読み取りが続行されないことを認識し、それを解放します。固定コードは次のようになります。

package main

func worker(c <-chan int) {
    var i int

    for {
        i += <-c
    }
}

func wrapper() {
    c := make(chan int)
    defer close(c) // fix here

    go worker(c)

    for i := 0; i < 0xff; i++ {
        c <- i
    }
}

func main() {
    for {
        wrapper()
    }
}
于 2013-05-16T15:22:04.193 に答える