Go の `sync.WaitGroup` で適切な同期を行うために、`wg.Add()` の配置が重要なのはなぜですか?

Linda Hamilton
リリース: 2024-10-30 01:49:02
オリジナル
225 人が閲覧しました

  Why is the Placement of `wg.Add()` Crucial for Proper Synchronization in Go's `sync.WaitGroup`?

WaitGroup 同期のための wg.Add() の配置の修正

Go では、sync.WaitGroup 型によってゴルーチン間の同期が提供されます。その主な目的は、メイン goroutine が goroutine のグループがタスクを完了するのを待機できるようにすることです。ただし、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>
ログイン後にコピー

wg.Add(1) 呼び出しは、匿名関数ですが、これは間違いです。この誤った配置により、同じゴルーチン内で wg.Done() の後に wg.Add(1) が実行されるため、wg.Wait() が途中で戻る状況が発生する可能性があります。その結果、v は完了したタスクの数を正確に反映せず、その値は 100 未満になる可能性があります。

修正された例では、

<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.Wait() を呼び出す前に、メインの goroutine が 100 個の goroutine すべてを呼び出し、それらの完了タスクを wg に登録したことを確認します。この正しい配置により、100 個のゴルーチンすべてがタスクを完了するまで wg.Wait() がブロックされ、v.

sync.WaitGroup を使用する一般規則:

sync.WaitGroup を使用して同期を確実に成功させるには、次のガイドラインに従ってください:

    新しい goroutine を開始する前に、常にメイン goroutine で wg.Add() を呼び出します。
  • goroutine パニックが発生した場合でも確実に実行されるように、defer ステートメントを使用して wg.Done() を呼び出すことをお勧めします。
  • sync.WaitGroup を他の関数に渡すとき (パッケージ レベルの変数の使用は避けてください) ) にポインタを渡してコピーを防止し、すべての変更が元の sync.WaitGroup.
  • に確実に行われるようにします。

以上がGo の `sync.WaitGroup` で適切な同期を行うために、`wg.Add()` の配置が重要なのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート