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 サイトの他の関連記事を参照してください。