ホームページ  >  記事  >  バックエンド開発  >  ゴルーチンから結果を収集するときにデッドロックを回避するにはどうすればよいですか?

ゴルーチンから結果を収集するときにデッドロックを回避するにはどうすればよいですか?

Patricia Arquette
Patricia Arquetteオリジナル
2024-11-06 14:22:02650ブラウズ

How to Avoid Deadlocks When Gathering Results from Goroutines?

データ処理にゴルーチンを使用する

Go では、ゴルーチンはタスクの同時実行を可能にする軽量のスレッドです。ゴルーチンを使用する場合、デッドロックを回避するために、処理後に結果を適切に収集することが重要です。

問題ステートメント

次のコード スニペットを検討してください:

sampleChan := make(chan sample)
var wg sync.WaitGroup

// Read from contents list
for i, line := range contents {
    wg.Add(1)
    // Process each item with a goroutine and send output to sampleChan
    go newSample(line, *replicatePtr, *timePtr, sampleChan, &wg)
}
wg.Wait()

// Read from sampleChan and put into a slice
var sampleList []sample
for s := range sampleChan {
    sampleList = append(sampleList, s)
}
close(sampleChan)

このコードは、ゴルーチンを使用してリスト内の項目を処理し、結果をスライスに収集しようとします。ただし、結果が収集される前にチャネルが閉じられるため、デッドロック エラーが発生します。

解決策

この問題を解決するには、結局、チャネルを非同期で閉じることができます。作業員が処理を終えました。修正されたコードは次のとおりです。

for i, line := range contents {
    wg.Add(1)
    // Process each item with a goroutine and send output to sampleChan
    go newSample(line, *replicatePtr, *timePtr, sampleChan, &wg)
}

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

for s := range sampleChan {
  ..
}

このコードは、アイテムを処理し、結果をsampleChanに送信するゴルーチンを開始します。同時に、すべてのワーカーが終了するのを待ってチャネルを閉じる別のゴルーチンも開始します。これにより、チャネルが閉じられる前にすべての結果が確実に収集されます。

代替ソリューション

コードの可読性とテスト容易性を向上させるために、同期 newSample 関数とハンドルを使用することをお勧めします。メインのゴルーチンの同時実行性。

for i, line := range contents {
    wg.Add(1)
    go func(line string) {
        defer wg.Done()
        sampleChan <- newSample(line, *replicatePtr, *timePtr)
    }(line)
}

このアプローチにより、同時実行プリミティブがローカライズされ、コードのメンテナンスが簡素化され、エラーのリスクが軽減されます。

以上がゴルーチンから結果を収集するときにデッドロックを回避するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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