ホームページ >バックエンド開発 >Golang >sync.WaitGroup ゴルーチンで chan を書き込む

sync.WaitGroup ゴルーチンで chan を書き込む

PHPz
PHPz転載
2024-02-09 17:00:10695ブラウズ

在sync.WaitGroup goroutine中写入chan

phpエディタYouziがsync.WaitGroupゴルーチンにchanを記述する方法を紹介します。同時プログラミングでは、sync.WaitGroup はゴルーチンのグループの実行が完了するのを待つことができる非常に便利な同期メカニズムです。ただし、場合によっては、ゴルーチンの実行が完了した後、他のゴルーチンが使用できるように結果を chan に書き込む必要があります。この記事では、この関数をsync.WaitGroupゴルーチンに実装する方法を詳しく紹介しますので、見てみましょう。

質問内容

API エンドポイントからアイテムのリストを取得しています。次に、プロジェクトごとに別の API リクエストを作成して、個々のプロジェクトに関するデータを取得します。

API トークンにはレート制限があり、同時に多数のリクエストを行うとスロットルが発生するため、各プロジェクトに 2 番目の API リクエストを同時に行うことはできません。

ただし、最初の API 応答データは複数のページに分割できるため、複数のページのデータを同時に処理できます。

いくつかの調査の結果、次のコードはまさに私が望んでいることを実行します:

リーリー

それが機能する理由を理解したい:

リーリー

最初の試みは失敗しました。wg.Wait() の後にチャネルを反復処理して、結果が results チャネルに書き込まれるときにその結果を読み取ることができると考えました。結果。

func main() {
    // pretend paginated results from initial API request
    page1 := []int{1, 2, 3}
    page2 := []int{4, 5, 6}
    page3 := []int{7, 8, 9}
    pages := [][]int{page1, page2, page3}

    results := make(chan string)

    var wg sync.WaitGroup
    for i := range pages {
        wg.Add(1)
        go func(i int) {
            defer wg.Done()
            for j := range pages[i] {
                // simulate making additional API request and building the report
                time.Sleep(500 * time.Millisecond)

                result := fmt.Sprintf("Finished creating report for %d", pages[i][j])
                results <- result
            }

        }(i)
    }

    go func() {
        wg.Wait()
        close(results)
    }()

    for result := range results {
        fmt.Println(result)
    }
}

回避策

最初の試行時:

  1. メインのゴルーチンにより、3 つのゴルーチンが結果チャネルに値を入れます。
  2. メイン コルーチンは、すべてのコルーチンが完了するまで待機します。
  3. ゴルーチンの 1 つが結果チャネルに値を入れ、チャネルを埋めます (チャネル サイズは 1 文字列です)。
  4. これで、3 つのゴルーチンはすべて結果チャネルに値を入れることができなくなり、結果チャネルが解放されるまでスリープ状態になります。
  5. すべての goroutine はスリープ状態です。あなたは行き​​詰まりに陥っています。

2 回目の試行:

  1. メインのゴルーチンには 4 つのゴルーチンが含まれています。
  2. 3 ゴルーチンは結果チャネルに値を入れます。
  3. もう 1 つのゴルーチン (4 番目と呼びます) は、これら 3 つのゴルーチンが終了するのを待ちます。
  4. 同時に、メイン コルーチンは結果チャネル (for ループ) の値を待ちます
  5. この場合、ゴルーチンの 1 つが結果チャネルに値を入れると、残りの 3 つのゴルーチンがブロックされ、メインのゴルーチンが結果チャネルから値を取り出し、それによって他のゴルーチンのブロックが解除されます。
  6. つまり、3 つのゴルーチンはすべてそれぞれの値を設定して終了です
  7. 次に、4 番目のゴルーチンがチャネルを閉じます
  8. メインのゴルーチンは for ループを終了します。

以上がsync.WaitGroup ゴルーチンで chan を書き込むの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はstackoverflow.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。