ホームページ >バックエンド開発 >Golang >「致命的なエラー: すべてのゴルーチンがスリープ中です - デッドロック!」を回避する方法sync.WaitGroup を使用しますか?

「致命的なエラー: すべてのゴルーチンがスリープ中です - デッドロック!」を回避する方法sync.WaitGroup を使用しますか?

Susan Sarandon
Susan Sarandonオリジナル
2024-12-21 06:57:09382ブラウズ

How to Avoid

「致命的なエラー: すべてのゴルーチンがスリープ状態です - デッドロック!」を理解するwith sync.WaitGroup

同時実行ゴルーチンを管理するために sync.WaitGroup パッケージを利用しようとする場合、恐ろしい「致命的エラー: すべてのゴルーチンがスリープ状態 - デッドロック!」を回避することが重要です。このエラーは、WaitGroup の誤った使用法、特に参照ではなくコピーによって値を渡す場合に発生します。

デッドロックの原因

この問題は、実際の WaitGroup オブジェクトを doWork 関数に渡すと、Go は値のコピーを作成します。これは、元の WaitGroup が、対応する Done() 呼び出しを行わずに、Add() 呼び出しを 10 回実行してカウンタをインクリメントしたことを意味します。対照的に、ゴルーチンに渡される WaitGroup の各コピーには、Done() 呼び出しが 1 つだけあり、WaitGroup がコピーされたときに存在していた数の Add() 呼び出しが含まれます。

解決策: 渡すWaitGroup

へのポインター このデッドロックを解決するには、WaitGroup

へのポインターを渡すことが不可欠です。 WaitGroup オブジェクト自体ではなく、WaitGroup。これにより、すべてのゴルーチンが同じ WaitGroup を参照するようになり、Done() を呼び出すと、減分カウンタが正しい 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{}
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go doWork(wg)
    }

    wg.Wait()
}

以下変更されたコードは、へのポインターの正しい使用法を示しています。 WaitGroup:

このアプローチを採用すると、WaitGroup でゴルーチンを自信を持って管理でき、デッドロックの落とし穴を回避し、効率的な同時実行を確保できます。

以上が「致命的なエラー: すべてのゴルーチンがスリープ中です - デッドロック!」を回避する方法sync.WaitGroup を使用しますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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