Golang プログラムでは、チャネルはゴルーチン間の通信を容易にします。ただし、以下のコードに示すように、チャネルを誤って使用するとデッドロックが発生する可能性があります:
<br>package main</p> <p>import (</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">"fmt" "sync"
)
func Push(c chan int, wg sync.WaitGroup) {
for i := 0; i < 5; i++ { c <- i } wg.Done()
}
func pull(c chan int, wg sync.WaitGroup) {
for i := 0; i < 5; i++ { result, ok := <-c fmt.Println(result, ok) } wg.Done()
}
func main() {
var wg sync.WaitGroup wg.Add(2) c := make(chan int) go push(c, wg) go pull(c, wg) wg.Wait() // Block the main thread until goroutines complete
}
このプログラムを実行すると、次のような問題が発生する可能性があります。次のエラー:
fatal error: all goroutines are asleep - deadlock!
このデッドロックが発生する理由を理解するために、コードを詳しく調べてみましょう:
問題は、WaitGroup がゴルーチンにどのように渡されるかにあります。アンパサンド (&) なしで値が渡される場合、その値は参照ではなく値によって渡されます。この場合、WaitGroup のコピーがゴルーチンごとに作成されます。
その結果、各ゴルーチンが wg.Done() を呼び出すと、WaitGroup のローカル コピーが変更されます。メインスレッドは、wg がすべてのゴルーチンの終了を示すまで待機するため、どちらのゴルーチンも元の WaitGroup を更新しないため、無限に待機します。これによりデッドロックが発生します。
この問題を解決するには、WaitGroup を参照で渡す必要があります。これにより、両方のゴルーチンが WaitGroup の同じインスタンスを変更し、その完了をメイン スレッドに正しく通知することが保証されます。
修正を加えたコードの改訂版は次のとおりです。
<br>パッケージ main</p> <p>import (</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">"fmt" "sync"
)
func Push(c chan int, wg *sync.WaitGroup) {
for i := 0; i < 5; i++ { c <- i } wg.Done()
}
func pull(c chan int, wg *sync.WaitGroup) {
for i := 0; i < 5; i++ { result, ok := <-c fmt.Println(result, ok) } wg.Done()
}
func main() {
var wg sync.WaitGroup wg.Add(2) c := make(chan int) go push(c, &wg) // Pass the WaitGroup by reference using the ampersand go pull(c, &wg) // Pass the WaitGroup by reference using the ampersand wg.Wait()
}
WaitGroup を参照渡しすることで、メインスレッドが両方のゴルーチンがいつタスクを完了したかを正確に判断できるようになり、デッドロックが回避されます。
以上がGo で WaitGroup を値で渡すとデッドロックが発生するのはなぜですか?また、それを解決するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。