プログラミング言語 golang go concurrent Go 言語待機グループ (sync.WaitGroup)

Go 言語待機グループ (sync.WaitGroup)

 
 
チャネルとミューテックスを使用して Go 言語で 2 つの同時プログラムを同期することに加えて、待機グループを使用して複数のタスクを同期することもできます。待機グループは、同時環境で指定された数のタスクの完了を保証できます。

 

sync.WaitGroup タイプでは、各 sync.WaitGroup 値は内部的に初期デフォルト値 0 のカウントを維持します。

以下の表に示すように、グループを待機するために使用できるいくつかの方法があります。

待機グループ方式
メソッド名 関数
(wg * WaitGroup) Add(delta int) 待機グループカウンター+1
(wg * WaitGroup) Done() 待機グループカウンター – 1
(wg * WaitGroup) Wait() 待機グループカウンターが 0 に等しくない場合、0 になるまでブロックします。

アドレス指定可能な sync.WaitGroup 値 wg の場合:

  • wg.Add(delta) メソッド呼び出しを使用して、値 wg によって維持されるカウントを変更できます。
  • メソッド呼び出し wg.Done() と wg.Add(-1) は完全に同等です。
  • wg.Add(delta) または wg.Done() 呼び出しによって、wg によって維持されるカウントが負の数に変更されると、パニックが発生します。
  • コルーチンが wg.Wait() を呼び出すと、
    • この時点で wg によって維持されているカウントが 0 である場合、この wg.Wait() 操作は no-op (noop) です。
    • それ以外の場合 (count は正の整数)、このコルーチンはブロッキング状態になります。後で他のコルーチンがこのカウントを 0 に変更すると (通常は wg.Done() を呼び出すことによって)、このコルーチンは再び実行状態に入ります (つまり、wg.Wait() が戻ります)。

待機グループ内にはカウンタがあり、メソッド呼び出しによってカウンタの値を増減させることができます。作業を行うために N 個の同時タスクを追加すると、待機グループ カウンターが N ずつ増加します。この値は、タスクが完了するたびに 1 ずつ減ります。同時に、別のゴルーチンでこの待機グループのカウンタ値が0になった場合は、すべてのタスクが完了したことを意味します。

次のコードは、このプロセスを示しています。

package main

import (
    "fmt"
    "net/http"
    "sync"
)

func main() {

    // ウェイトグループを宣言する
    var wg sync.WaitGroup

    // 複数のウェブサイトのアドレスを用意する
    var urls = []string{
        "http://www.github.com/",
        "https://www.yahoo.com/",
        "https://www.golang.com/",
    }

    // これらのアドレスをループ処理する
    for _, url := range urls {

        // それぞれのタスクが開始すると、ウェイトグループを1つ増やす
        wg.Add(1)

        // 並列処理を開始する
        go func(url string) {

            // 関数が完了する際に、ウェイトグループの値を1つ減らすためにdeferを使用する
            defer wg.Done()

            // httpを使用して提供されたアドレスにアクセスする
            _, err := http.Get(url)

            // アドレスとエラーをプリントする
            fmt.Println(url, err)

            // urlアドレスをパラメーターとして渡す
        }(url)
    }

    // すべてのタスクが完了するまで待つ
    wg.Wait()

    fmt.Println("over")
} 

コードの説明は次のとおりです。

  • 12 行目では待機グループを宣言しています。タスクごとに待機グループを使用するのではなく、待機中のタスクのグループに必要な待機グループは 1 つだけです。
  • 15 行目では、アクセス可能な Web サイトのアドレスの一連の文字列スライスを準備します。
  • 行 22 では、これらの文字列スライスを反復処理します。
  • 25行目では、待機グループのカウンタに1を加算します。つまり、各タスクに1を加算します。
  • 28 行目で、匿名関数の同時実行が有効になっています。
  • 行 31、この文は匿名関数の最後に実行され、タスクの完了を示します。 wg.Done() メソッドは、wg.Add(-1) を実行するのと同じです。
  • 34 行目では、http パッケージによって提供される Get() 関数を使用して URL にアクセスします。Get() 関数は、Web サイトが応答するかタイムアウトになるまでブロックされます。
  • 37 行目は、サイトが応答してタイムアウトになった後、サイトのアドレスと考えられるエラーを出力します。
  • 40 行目では、URL 変数がクロージャを通じて匿名関数に入れられた後に変更されるという問題を回避するために、ゴルーチンのパラメータを通じて URL が渡されます。
  • 44 行目、すべての Web サイトが応答するかタイムアウトするのを待った後、タスクが完了し、Wait はブロックを停止します。
 

「 Go 言語待機グループ (sync.WaitGroup)」についてわかりやすく解説!絶対に観るべきベスト2動画

【golang】goroutine その➀ sync.WaitGroup
How does “Golang Sync Waitgroup” work | Golang Tutorial For Beginners