データ処理にゴルーチンを使用する
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 サイトの他の関連記事を参照してください。