ホームページ  >  記事  >  バックエンド開発  >  ポインターの代わりに値を渡すと Go チャネルでデッドロックが発生するのはなぜですか?

ポインターの代わりに値を渡すと Go チャネルでデッドロックが発生するのはなぜですか?

Barbara Streisand
Barbara Streisandオリジナル
2024-10-28 21:44:02288ブラウズ

Why Does Passing Values Instead of Pointers Cause Deadlock in Go Channels?

Go チャネルのデッドロック エラー

Go では、チャネルはゴルーチン間の通信手段を提供します。ただし、チャネルを不適切に使用すると、ゴルーチンが無期限にブロックされるデッドロックが発生する可能性があります。

チャネルでデッドロックが発生する一般的な原因の 1 つは、ゴルーチン関数でポインターの代わりに値の型を渡す場合です。これは、Go が値の型を値で渡すため、つまり値のコピーが作成されるためです。

次の例を考えてみましょう:

<code class="go">import (
    "fmt"
    "sync"
)

func push(c chan int, wg sync.WaitGroup) {
    for i := 0; i < 5; i++ {
        c <- i
    }
    wg.Done()
}

func pull(c chan int, wg sync.WaitGroup) {
    for i := 0; i < 5; i++ {
        result, ok := <-c
        fmt.Println(result, ok)
    }
    wg.Done()
}

func main() {
    var wg sync.WaitGroup
    wg.Add(2)
    c := make(chan int)

    go push(c, wg)
    go pull(c, wg)

    wg.Wait()
}</code>

プログラムを実行するとデッドロック エラーが発生します:

    0 true
    1 true
    2 true
    3 true
    4 true
    throw: all goroutines are asleep - deadlock!

デッドロックは、WaitGroup が値としてプッシュ関数とプル関数に渡されるために発生します。 WaitGroup がいずれかのゴルーチンで更新されても、他のゴルーチンには値のコピーがあるため、その変更は反映されません。

デッドロックを解決するには、WaitGroup をポインターとして渡す必要があります。これにより、両方のゴルーチンが WaitGroup の同じインスタンス上で動作することが保証されます。

コードの修正バージョンは次のとおりです:

<code class="go">import (
    "fmt"
    "sync"
)

func push(c chan int, wg *sync.WaitGroup) {
    for i := 0; i < 5; i++ {
        c <- i
    }
    wg.Done()
}

func pull(c chan int, wg *sync.WaitGroup) {
    for i := 0; i < 5; i++ {
        result, ok := <-c
        fmt.Println(result, ok)
    }
    wg.Done()
}

func main() {
    var wg sync.WaitGroup
    wg.Add(2)
    c := make(chan int)

    go push(c, &wg)
    go pull(c, &wg)

    wg.Wait()
}</code>

以上がポインターの代わりに値を渡すと Go チャネルでデッドロックが発生するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。