ホームページ  >  記事  >  バックエンド開発  >  Go で同期を保証するには、なぜ wg.Add() の配置が重要なのでしょうか?

Go で同期を保証するには、なぜ wg.Add() の配置が重要なのでしょうか?

DDD
DDDオリジナル
2024-10-27 20:40:03636ブラウズ

Why is wg.Add() Placement Crucial for Guaranteed Synchronization in Go?

保証された同期のための wg.Add() の位置

問題

以下の Go コードでは、変数 v が予想よりも小さいことがよくあります。 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>

Solution

wg.Add() は、対応するゴルーチンを起動する前に常に呼び出す必要があります。これにより、メインのゴルーチンがすべてのゴルーチンをブロックするようになります。ゴルーチンが wg.Done() を実行しました。

<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() がゴルーチン内に配置されている場合、すべてのゴルーチンが完了するまでメインのゴルーチンがブロックされることは保証できません。 。これは、ゴルーチンが同時に実行され、実行順序が決定的でないためです。

ゴルーチンの前に wg.Add() を配置することで、メインのゴルーチンが到達する前に wg.Add() を 100 回呼び出すことが保証されます。 wg.Wait()。これにより、100 個のゴルーチンすべてが wg.Done() を呼び出すまでメインのゴルーチンがブロックされ、v が常に 100 に等しくなります。

ベスト プラクティス

sync.WaitGroup を使用する場合は、次に従ってください。ガイドライン:

  • go を使用して新しいゴルーチンを開始する前に、「元の」ゴルーチンで wg.Add() を呼び出します。
  • 確実に実行するには、defer ステートメントを使用して wg.Done() を呼び出します。ゴルーチンがパニックになった場合でも呼び出されます。
  • wg を他の関数に渡すときは、wg 構造体のコピーの作成を避けるためにポインターを渡します。

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

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