ゴルーチンのデッドロックの解決
同時 Golang プログラムを使用している場合、デッドロック エラーが発生する可能性があります。「致命的なエラー: すべてのゴルーチンがスリープ状態です -行き詰まり!」。このエラーは、複数のゴルーチンがタスクの実行を互いに待機しており、デッドロック状況が生じている場合に発生します。
次のコードを考えてみましょう:
<code class="go">func producer(ch chan int, d time.Duration, num int) { for i := 0; i < num; i++ { ch <- i time.Sleep(d) } } func main() { ch := make(chan int) go producer(ch, 100*time.Millisecond, 2) go producer(ch, 200*time.Millisecond, 5) for { fmt.Println(<-ch) } close(ch) }</code>
このコードは、値を送信する 2 つのプロデューサー ゴルーチンを作成します。同じチャンネルに。メインのゴルーチンは、無限ループでチャネルから値を継続的に受信します。
この問題は、プロデューサーが「短命」であり、有限時間が経過すると値の送信を停止するために発生しますが、メインのゴルーチンは値を受信し続けます。際限なく。これ以上値が送信されないことを示すためにチャネルが閉じられることがないため、デッドロックが発生します。
このデッドロックを解決するには、すべてのプロデューサーがタスクを完了したときにチャネルが閉じられるようにする必要があります。これを効率的に実現する方法は、sync.WaitGroup のような同期プリミティブを使用することです。
コードの修正版を次に示します。
<code class="go">func producer(ch chan int, d time.Duration, num int, wg *sync.WaitGroup) { defer wg.Done() for i := 0; i < num; i++ { ch <- i time.Sleep(d) } } func main() { wg := &sync.WaitGroup{} ch := make(chan int) wg.Add(1) go producer(ch, 100*time.Millisecond, 2, wg) wg.Add(1) go producer(ch, 200*time.Millisecond, 5, wg) go func() { wg.Wait() close(ch) }() for v := range ch { fmt.Println(v) } }</code>
このコードでは、同期を渡します。各プロデューサーのゴルーチンへの WaitGroup。各プロデューサーは開始前に待機グループをインクリメントし、終了時にデクリメントします。メインのゴルーチンは、wg.Wait() を使用してすべてのプロデューサーの完了を待ちます。すべてのプロデューサーが終了すると、メインの goroutine がチャネルを閉じます。
このソリューションにより、すべてのプロデューサーが作業を完了した後にのみチャネルが閉じられるようになり、デッドロック状況が回避されます。
以上がGoroutine と Channel を使用するときに Golang でデッドロックを防ぐ方法は?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。