並行プログラミングのテクニック: GoのWaitGroupの高度な使い方

Go言語の並行プログラミングで、WaitGroupは、一連の並行操作の完了を待機するのに非常に役立つツールです。基本的な使用方法に加えて、WaitGroupには、並行プログラミングをより柔軟かつ効率的にすることができる高度な使用方法がいくつかあります。

  1. 待機数を動的に増やすためにAddメソッドを使用する

並行処理の数が事前に分からない場合でも、処理が完了するまで待機を行いたいケースがあります。 このとき、WaitGroupのAddメソッドを用いて、待機する数を動的に増やすことができます。

var wg sync.WaitGroup
// 模拟并发操作
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
// 并发操作的逻辑
wg.Done()
}()
}
wg.Wait()

上の例では、あらかじめその数を知らせることなく、ループで10個の同時操作を追加しています。それぞれの同時操作は完了した時点でWaitGroupのDoneメソッドを呼び出して完了を伝え、最後にWaitメソッドによってすべての操作の完了を待ちます。

  1. WaitGroupのWaitメソッドでタイムアウトを設定する

WaitGroupのWaitメソッドをselect文と併用することでタイムアウトを設けた待ち合わせができます。例:

var wg sync.WaitGroup
// 模拟并发操作
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
// 并发操作的逻辑
wg.Done()
}()
}
timeout := 5 * time.Second
done := make(chan struct{})
go func() {
wg.Wait()
close(done)
}()
select {
case <-done:
// 所有操作完成
case <-time.After(timeout):
// 超时
}

上の例では、goroutineをさらに1つ使用してWaitメソッドを実行し、待機完了後にdoneというチャネルをクローズします。次に、メインのgoroutineでselect文を使ってdoneチャネルがクローズされるかタイムアウトを待つことで、待機を続けるかどうかを決定します。

  1. WaitGroupのWaitメソッドを活用して、同時実行タスクの一部完了を待機

ある場合、複数の並行タスクの中で、一部のタスクが完了したら以降の処理を実行したいのに、すべてのタスクの完了を待たなければならない場合があります。その場合はWaitGroupのWaitメソッドとチャネルを組み合わせることで、部分完了を実現できます。例えば、

var wg sync.WaitGroup
// 模拟并发操作
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
// 并发操作的逻辑
wg.Done()
}()
}
done := make(chan struct{})
go func() {
wg.Wait()
close(done)
}()
// 部分完成的逻辑
select {
case <-done:
// 所有操作完成
default:
// 部分操作完成
}

上の例では、Wait メソッドの実行と wait の完了後にチャンネルを閉じるために、追加の goroutine を同様に使用します。そのあと、メインの goroutine で select ステートメントを使用して、done チャンネルが閉じられているかどうかを判断します。この判断により、そのまま待つか、完了部分のロジックを実行するかが決まります。

まとめ

WaitGroupの高度な使い方は、並行処理の完了をより柔軟に扱うのに役立ちます。Waitの数を動的に増やしたり、タイムアウトを設定したり、完了の一部を実現したりすることで、並行プログラミングのプロセスと効率をより適切に制御できます。実際の並行プログラミングでは、特定のニーズに応じて適切なWaitGroupの使用法を選択することで、コードをより信頼性が高く効率的にすることができます。

bannerAds