WaitGroup とバッファリングされたチャネルによる Go のデッドロック
Go では、複数の goroutine が互いの完了を待っているときにデッドロックが発生します。膠着状態にある。この状況は、バッファリングされたチャネルと WaitGroups を誤って使用すると発生する可能性があります。
次のコードを考えてみましょう:
<code class="go">package main import "fmt" import "sync" func main() { ch := make(chan []int, 4) var m []int var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go func() { defer wg.Done() ch <- m return }() } wg.Wait() for c := range ch { fmt.Printf("c is %v", c) } }</code>
このコードは、バッファ サイズ 4 のチャネルを作成し、5 つのゴルーチンを開始することが想定されています。 、それぞれが空のスライスをチャネルに送信します。メインの goroutine は、すべての goroutine が終了するのを待ってから、チャネル上で範囲を広げます。
ただし、このコードではデッドロックが発生します。なぜですか?
デッドロックの原因:
コードには 2 つの問題があります:
解決策:
チャネル容量を増やす: チャネル容量を 5 に増やすと、すべてのゴルーチンがブロックせずに値を送信するのに十分なスロットが利用可能になります。さらに、ゴルーチンの書き込みが終了した後にチャネルを閉じると、これ以上要素が来ないことが範囲ループに通知され、無限に待機することがなくなります。
<code class="go">ch := make(chan []int, 5) ... wg.Wait() close(ch)</code>
Use Done () ループ内: チャネルを閉じる代わりに、WaitGroup の Done() メソッドを使用して、最後のゴルーチンが終了したことを知らせることができます。範囲ループ内で Done() を呼び出すことで、チャネルが空になったときにメインの goroutine に通知され、ループを終了できます。
<code class="go">go func() { for c := range ch { fmt.Printf("c is %v\n", c) wg.Done() } }() wg.Wait()</code>
これらのソリューションは、次のことを保証することでデッドロックを解決します。チャネルに十分な容量があり、チャネルから読み取る要素がなくなったときに範囲ループが終了すること。
以上がWaitGroup とバッファリングされたチャネルを使用して提供された Go コードでデッドロックが発生するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。