ホームページ >バックエンド開発 >Golang >Go プログラムが「すべてのゴルーチンがスリープ状態です」エラーでデッドロックするのはなぜですか?

Go プログラムが「すべてのゴルーチンがスリープ状態です」エラーでデッドロックするのはなぜですか?

DDD
DDDオリジナル
2024-12-23 02:11:14931ブラウズ

Why Does My Go Program Deadlock with the

Go プログラムのデッドロック: "throw: すべてのゴルーチンがスリープ状態です"

Go プログラムでは、2 つ以上のゴルーチン (同時に実行している関数)は、お互いが完了するまで無期限に待ちます。このような状況の 1 つは、次のプログラムに見られるように、チャネルを操作するときに発生する可能性があります:

package main

import (
    "fmt"
)

func total(ch chan int) {
    res := 0
    for iter := range ch {
        res += iter
    }
    ch <- res
}

func main() {
    ch := make(chan int)
    go total(ch)
    ch <- 1
    ch <- 2
    ch <- 3
    fmt.Println("Total is ", <-ch)
}

このプログラムを実行すると、パニック メッセージが表示されます:

throw: all goroutines are asleep - deadlock!

これの根本原因デッドロックは、全体の goroutine が受信元と同じチャネル (ch) に値を送り返そうとするという事実にあります。チャネルが閉じられていない (シグナル伝達完了) ため、ゴルーチン全体の範囲ループが無期限に継続し、それ以降の送信または受信がブロックされます。

この問題を解決するには、結果を受信する別のチャネルを導入できます。更新されたプログラムは次のとおりです。

package main

import (
    "fmt"
)

func total(in chan int, out chan int) {
    res := 0
    for iter := range in {
        res += iter
    }
    out <- res // Send result on separate channel
}

func main() {
    ch := make(chan int)
    rch := make(chan int) // New channel to receive result
    go total(ch, rch)
    ch <- 1
    ch <- 2
    ch <- 3
    close(ch) // Explicitly close channel to end loop in `total`
    result := <-rch // Wait for result on `rch`
    fmt.Println("Total is ", result)
}

結果を別のチャネルで送信し、元のチャネルを閉じることで、デッドロックが解消され、メインの goroutine が計算された合計を受信できるようになります。

以上がGo プログラムが「すべてのゴルーチンがスリープ状態です」エラーでデッドロックするのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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