ホームページ >バックエンド開発 >Golang >同時実行 Go プログラムのどこに「wg.Add()」を配置する必要がありますか?

同時実行 Go プログラムのどこに「wg.Add()」を配置する必要がありますか?

Susan Sarandon
Susan Sarandonオリジナル
2024-10-26 13:28:02995ブラウズ

 Where Should You Place `wg.Add()` in Concurrent Go Programs?

wg.Add() の配置を理解する

同時実行 Go プログラムでは、sync.WaitGroup 型はタスクの完了を調整する同期プリミティブとして機能します。 WaitGroup を操作する場合、適切な待機動作を確保するには、どこに wg.Add() 呼び出しを配置するかが重要です。

次のコードを検討してください。

<code class="go">var wg sync.WaitGroup
var v int32 = 0

for i := 0; i < 100; i++ {
    go func() {
        wg.Add(1) // wrong place
        atomic.AddInt32(&v, 1)
        wg.Done()
    }()
}
wg.Wait()
fmt.Println(v)</code>

このコードは、一連のタスクと共有変数 v のインクリメントを同時に実行します。ただし、出力の結果は 100 未満の値になることがよくあります。問題は、匿名ゴルーチン内での wg.Add(1) の配置にあります。

wg.Add(1) をゴルーチン内に配置すると、メインgoroutine は、wg.Done() が呼び出される前に実行を再開する場合があります。これは、同時実行モデルにより wg.Add(1) 呼び出しと wg.Done() 呼び出しの両方の同時実行が許可されており、メインの goroutine での待機が途中で終了する可能性があるために発生する可能性があります。

これを解決するには

<code class="go">var wg sync.WaitGroup
var v int32 = 0

for i := 0; i < 100; i++ {
    wg.Add(1)
    go func() {
        atomic.AddInt32(&v, 1)
        wg.Done()
    }()
}
wg.Wait()
fmt.Println(v)</code>

wg.Add(1) をゴルーチンの外に移動することで、メインのゴルーチンが確実にブロックされるようにします。すべてのゴルーチンが完了して wg.Done() を呼び出すまで、wg.Wait() 呼び出しを実行します。これにより、v の最終値が正確であることが保証されます。

一般的な方法として、wg.Done() を呼び出すゴルーチンを起動する前に、常に wg.Add() を呼び出すことをお勧めします。これにより、適切な待機動作が保証され、発生する可能性のある競合状態が排除されます。

以上が同時実行 Go プログラムのどこに「wg.Add()」を配置する必要がありますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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