ホームページ >バックエンド開発 >Golang >`sync.WaitGroup` を使用すると「致命的なエラー: すべてのゴルーチンがスリープ状態になっています - デッドロック!」が発生するのはなぜですか? どうすれば修正できますか?

`sync.WaitGroup` を使用すると「致命的なエラー: すべてのゴルーチンがスリープ状態になっています - デッドロック!」が発生するのはなぜですか? どうすれば修正できますか?

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-12-04 20:52:13359ブラウズ

Why Does Using `sync.WaitGroup` Lead to

sync.WaitGroup 使用時の「致命的エラー: すべてのゴルーチンがスリープ中 - デッドロック」の理解と解決

sync.WaitGroup を使用して複数のゴルーチンの完了を調整しようとする場合、「致命的なエラー: すべてのゴルーチンがスリープ状態です - デッドロック!」というエラーが発生する可能性があります。この不可解なメッセージは、特にコードがドキュメントの例に従って記述されているように見える場合に、不可解になる可能性があります。

このエラーの原因は、Go が関数に渡される値を処理する方法にあります。 sync.WaitGroup オブジェクトを直接渡す場合、Go はその値のコピーを作成し、基本的には異なるオブジェクトを各 goroutine に渡します。これにより、元の WaitGroup とゴルーチンが動作するコピーとの間に切断が作成されます。

この問題の解決策は、代わりに sync.WaitGroup へのポインターを渡すことです。そうすることで、すべてのゴルーチンが同じ基礎となるオブジェクトを参照し、その内部カウンターで一貫して動作するようになります。ポインターを使用した正しいコードを以下に示します。

import "sync"

func doWork(wg *sync.WaitGroup) error {
    defer wg.Done()
    // Do some heavy lifting... request URL's or similar
    return nil
}

func main() {
    wg := &sync.WaitGroup{} // Use pointer to pass the WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go doWork(wg)
    }
}

この変更により、ゴルーチンは WaitGroup オブジェクトと適切に対話し、作業を開始する前にカウンターをインクリメントし、完了時にカウンターをデクリメントします。その結果、メイン関数の WaitGroup.Wait() 呼び出しが無期限にブロックされることはなく、プログラムは期待どおりに実行されます。

以上が`sync.WaitGroup` を使用すると「致命的なエラー: すべてのゴルーチンがスリープ状態になっています - デッドロック!」が発生するのはなぜですか? どうすれば修正できますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。