ホームページ >バックエンド開発 >Golang >バッファーされたチャネルをセマフォとして使用する場合、すべてのゴルーチンが確実に終了するようにするにはどうすればよいですか?

バッファーされたチャネルをセマフォとして使用する場合、すべてのゴルーチンが確実に終了するようにするにはどうすればよいですか?

Susan Sarandon
Susan Sarandonオリジナル
2024-12-02 00:54:13563ブラウズ

How Can I Ensure All Goroutines Finish When Using a Buffered Channel as a Semaphore?

WaitGroup を使用したバッファーされたチャネルの空の待機

同時プログラミングでは、多くの場合、同時に実行するゴルーチンの数を制御する必要があります。一般的なアプローチは、バッファリングされたチャネルをセマフォとして使用することです。ただし、このアプローチの制限に注意することが重要です。

次の例を考えてみましょう:

ints := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
 sem := make(chan struct{}, 2)
for _, i := range ints {
  sem<- struct{}{}
  go func(id int, sem chan struct{}) {
    // do something
    <-sem
  }(i, sem)
}

このコードは、サイズ 2 のバッファー チャネル (sem) を使用して、同時接続数を制限しています。ただし、問題があります。最後のいくつかのゴルーチンがタスクを完了する前にプログラムが終了する可能性があります。これは、プログラムがさらにゴルーチンをディスパッチしている間であっても、処理中のどの時点でもバッファリングされたチャネルが空になる可能性があるためです。

バッファリングされたチャネルが空になるのを待つために、チャネル自体に依存することはできません。代わりに、sync.WaitGroup を使用して、未処理の goroutine の数を追跡できます。

sem := make(chan struct{}, 2)
var wg sync.WaitGroup
for _, i := range ints {
  wg.Add(1)
  sem<- struct{}{}
  go func(id int) {
    defer wg.Done()
    // do something
    <-sem
  }(i)
}
wg.Wait()

この変更されたコードでは、wg.Add(1) を使用して、各 goroutine をディスパッチする前に待機グループをインクリメントします。 defer wg.Done() ステートメントは、ゴルーチンがタスクを完了したときに待機グループをデクリメントします。最後に、wg.Wait() は待機グループが 0 に達するまでブロックし、すべてのゴルーチンの実行が確実に終了します。このアプローチにより、チャネルが空になるのを待つことができ、プログラムが途中で終了することがなくなります。

以上がバッファーされたチャネルをセマフォとして使用する場合、すべてのゴルーチンが確実に終了するようにするにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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