コンカレント プログラミング スキル: Go WaitGroup の高度な使用法
コンカレント プログラミングでは、複数の同時タスクの実行を調整および管理することが重要なタスクです。 Go 言語は、非常に実用的な同時実行プリミティブである WaitGroup を提供します。これは、同時実行制御をエレガントに実装するのに役立ちます。この記事では、WaitGroup の基本的な使用法を紹介し、読者がそれをよりよく理解して適用できるように、具体的なコード例を使用してその高度な使用法に焦点を当てます。
WaitGroup は Go 言語に組み込まれた同時実行プリミティブで、同時タスクの完了を待つのに役立ちます。これには、Add、Done、Wait の 3 つのメソッドが用意されています。 Add メソッドは待機中のタスクの数を設定するために使用され、Done メソッドは待機中のタスクの数を減らすために使用され、Wait メソッドは待機中のすべてのタスクが完了するまで現在のコルーチンをブロックするために使用されます。
以下は、WaitGroup の基本的な使用法を示す簡単な例です。
package main import ( "fmt" "sync" "time" ) func main() { var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go func(num int) { defer wg.Done() time.Sleep(time.Second) fmt.Println("Task", num, "done") }(i) } wg.Wait() fmt.Println("All tasks done") }
上記のコードでは、WaitGroup オブジェクト wg を作成し、ループを通じて 5 つの同時タスクを作成します。各タスクの実行中に、Add メソッドを使用して待機中のタスクの数を増やし、タスクの終了時に Done メソッドを使用して待機中のタスクの数を減らします。最後に、Wait メソッドを呼び出して、待機中のタスクがすべて完了するまでメイン コルーチンをブロックします。
WaitGroup では、基本的な使用法に加えて、同時タスクの実行をより柔軟に制御できる高度な使用法も提供しています。以下では、一般的に使用される高度な使用法をいくつか詳しく紹介します。
一連のタスクを同時に実行する必要があるが、最大数を制限したい場合同時実行性を実現するには、バッファリングされたチャネルの組み合わせ WaitGroup を使用します。以下のコードは、一連のタスクを同時に実行する方法を示していますが、同時に実行できるタスクは 3 つまでです:
package main import ( "fmt" "sync" "time" ) func main() { var wg sync.WaitGroup maxConcurrency := 3 tasks := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} sem := make(chan struct{}, maxConcurrency) for _, task := range tasks { wg.Add(1) sem <- struct{}{} // 获取令牌,控制最大并发数 go func(num int) { defer wg.Done() time.Sleep(time.Second) fmt.Println("Task", num, "done") <-sem // 释放令牌,允许新的任务执行 }(task) } wg.Wait() fmt.Println("All tasks done") }
上記のコードでは、バッファリングされたチャネル sem を作成し、そのサイズを次のように設定します。同時実行の最大数。各タスクを開始する前に、sem <- struct{}{} ステートメントを通じてトークンを取得します。タスクが完了したら、<-sem ステートメントを使用してトークンを解放します。トークンの取得と解放を制御することで、同時実行の最大数を制限できます。
同時タスクの実行時間を制御し、タイムアウトになったらタスクの実行を終了したい場合があります。バッファリングされたチャネルとタイマーを使用すると、この機能を簡単に実装できます。次のコードは、同時タスクのタイムアウトを 3 秒に設定する方法を示しています。
package main import ( "fmt" "sync" "time" ) func main() { var wg sync.WaitGroup tasks := []int{1, 2, 3, 4, 5, 6, 7} timeout := 3 * time.Second done := make(chan struct{}) for _, task := range tasks { wg.Add(1) go func(num int) { defer wg.Done() // 模拟任务执行时间不定 time.Sleep(time.Duration(num) * time.Second) fmt.Println("Task", num, "done") // 判断任务是否超时 select { case <-done: // 任务在超时前完成,正常退出 return default: // 任务超时,向通道发送信号 close(done) } }(task) } wg.Wait() fmt.Println("All tasks done") }
上記のコードでは、done チャネルを作成し、タスクの実行中にチャネルが閉じられているかどうかを確認して、タスクが実行されているかどうかを判断します。タイムアウト。タスクが完了すると、close(done) ステートメントを使用して、done チャネルにシグナルを送信し、タスクがタイムアウトしたことを示します。さまざまな状況に対処するには、select ステートメントを通じてさまざまなブランチを選択します。
上記のサンプル コードを通じて、WaitGroup の高度な使用法が実際の同時プログラミングで非常に実用的であることがわかります。これらのテクニックを習得すると、同時タスクの実行をより適切に制御し、コードのパフォーマンスと保守性を向上させることができます。この記事の紹介とサンプルコードを通じて、WaitGroup の使い方を深く理解し、実際のプロジェクトに適用していただければ幸いです。
以上が同時プログラミング スキル: Go WaitGroup の高度な使用法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。