ホームページ >バックエンド開発 >Golang >Go WaitGroup によって「すべての Goroutines Are Aleep - Deadlock!」が発生するのはなぜですか?エラー?

Go WaitGroup によって「すべての Goroutines Are Aleep - Deadlock!」が発生するのはなぜですか?エラー?

Barbara Streisand
Barbara Streisandオリジナル
2024-12-25 19:14:17796ブラウズ

Why Does My Go WaitGroup Cause a

WaitGroup デッドロック: 「すべてのゴルーチンがスリープ状態 - デッドロック!」を理解する

WaitGroup を使用してゴルーチンを調整しようとすると、次のような問題が発生する可能性があります。エラー「致命的エラー: すべてのゴルーチンがスリープ中 - デッドロック!」。これは、WaitGroup のカウンターをデクリメントするゴルーチンが誤ってスリープ状態になった場合に発生します。

問題:

次の Go コードは、このエラーがどのように発生するかを示しています。

package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            fmt.Println("Hello", i)
        }()
    }
    wg.Wait()
}

実行すると、このコードはそれぞれに対して「Hello」を出力するはずです。ゴルーチン。ただし、代わりに、プログラムは恐ろしい「デッドロック」エラーで終了します。

理由:

問題は、WaitGroup がゴルーチンに渡される方法にあります。 Go は、値が匿名関数に渡されるときに、その値のコピーを作成します。したがって、各ゴルーチンは WaitGroup の個別のコピーで動作し、いずれのゴルーチンもカウンタをデクリメントしないため、ゴルーチンは永続的にスリープ状態になります。

解決策:

デッドロックを解決するには、WaitGroup 自体ではなく、WaitGroup へのポインタを渡す必要があります。したがって、すべてのゴルーチンは同じ WaitGroup を参照し、そのカウンタを正しくデクリメントできるようになります。

package main

import (
    "fmt"
    "sync"
)

func main() {
    wg := &sync.WaitGroup{}
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            fmt.Println("Hello", i)
        }()
    }
    wg.Wait()
}

ポインタを渡すことにより、ゴルーチンは同じ WaitGroup オブジェクトを共有し、実行を正常に調整できます。このバージョンのコードは、デッドロックを引き起こすことなく、各 goroutine に対して「Hello」を正しく出力します。

以上がGo WaitGroup によって「すべての Goroutines Are Aleep - Deadlock!」が発生するのはなぜですか?エラー?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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