Go のデッドロック: WaitGroup とバッファリングされたチャネル
Go では、同時ゴルーチンが互いの完了を無限に待機すると、デッドロックが発生します。デッドロックの一般的な原因の 1 つは、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 // Sending to a full channel return }() } wg.Wait() for c := range ch { fmt.Printf("c is %v", c) } }</code>
このコードは、5 つの空のスライスを容量 4 のバッファリングされたチャネルに送信し、すべてのゴルーチンが完了した後にチャネルから読み取ることを目的としています。ただし、このコードではデッドロック エラーが発生します。
デッドロックの原因
デッドロックは、次の 2 つの問題によって発生します。
Solution
デッドロックを解決するには、次のいずれかの変更を加えます:
解決策 1:
チャネル容量を 5 (またはそれ以上) に増やし、すべてのデータを送信した後にチャネルを閉じます。 :
<code class="go">ch := make(chan []int, 5) ... wg.Wait() close(ch)</code>
解決策 2:
チャネルから読み取る別の goroutine を開始し、すべてのデータが受信されたときにメインの goroutine に通知します:
<code class="go">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() { ch <- m wg.Done() }() } go func() { for c := range ch { fmt.Printf("c is %v\n", c) wg.Done() } }() wg.Wait() }</code>
以上がGo で WaitGroups とバッファリングされたチャネルを使用するときにデッドロックを防ぐにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。