Go チャネルとデッドロック: ブロッキングの問題について
Go チャネルを使用する場合、適切な同期が確保されていないとデッドロックが発生する可能性があります。次の例を考えてみましょう。
<code class="go">func main() { c1 := make(chan int) c2 := make(chan int) // Create two goroutines that ping-pong values between channels go func() { for i := range c1 { println("G1 got", i) c2 <- i } }() go func() { for i := range c2 { println("G2 got", i) c1 <- i } }() // Send an initial value to start the chain c1 <- 1 // Wait for a long time to observe the ping-ponging behavior time.Sleep(1000000000 * 50) }</code>
このコードは、main 関数が終了するまで、値を無期限に正常に出力します。ただし、別の値がチャネルの 1 つに送信されると、デッドロックが発生します:
<code class="go">func main() { c1 := make(chan int) c2 := make(chan int) // Create two goroutines to ping-pong values between channels go func() { for i := range c1 { println("G1 got", i) c2 <- i } }() go func() { for i := range c2 { println("G2 got", i) c1 <- i } }() // Send an initial value to start the chain c1 <- 1 // Wait for a short time time.Sleep(1000000000 * 1) // Send another value to the channel c1 <- 2 // Wait for a long time to observe the issue time.Sleep(1000000000 * 50) }</code>
この場合、値 "2" を送信した後に出力が停止します:
G1 got 1 G2 got 1 G1 got 1 G2 got 1 G1 got 2
この問題は、ゴルーチンがそれぞれのチャネルから値を受信するのをお互いに待機しているために発生します。したがって、どちらのゴルーチンも進行できず、デッドロックが発生します。
デッドロックを防ぐには、チャネルが適切に同期されていることを確認してください。 1 つのアプローチは、次の例のように、ゼロ以外の容量を持つバッファーされたチャネルを使用することです。
<code class="go">// ... (Same code as before) c1 := make(chan int, 1) // Buffered channel with capacity of 1 c2 := make(chan int, 1)</code>
バッファーされたチャネルを使用すると、他のゴルーチンが前のゴルーチンをまだ受信していない場合でも、1 つのゴルーチンは値を送信できます。 1つ。これは、前述のような状況でのデッドロックを回避するのに役立ちます。
以上がGo チャネルがデッドロックを引き起こす理由と、それを防ぐにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。