すべての作業が完了したときに、複数のゴルーチンで満たされたチャネルをどのように閉じるかは、よく話題になる質問です。 Go では、チャネルを閉じることは、データがもうないことを受信者に通知する方法です。チャネルを閉じることにより、受信者は、送信者がすべての送信操作を完了したことを時間内に知ることができます。複数のゴルーチンで満たされたチャネルでは、カウンターを使用して、さらにいくつのゴルーチンがチャネルにデータを送信しているかを追跡できます。カウンタが 0 に下がると、すべての作業が完了し、チャネルを安全に閉じることができます。チャネルを閉じた後、受信側は、受信式で追加の変数を使用して、チャネルが閉じられたかどうかを判断できます。このようにして、すべての作業が完了した後に複数のゴルーチンによって満たされたチャネルが適切に閉じられるようにすることができ、リソース リークやデッドロックの問題を回避できます。
「共有メモリで通信するのではなく、通信でメモリを共有する」というGoのやり方に従い、チャネルを使ってやるべきことを非同期に伝えようとしています。 and send タスクの処理結果を返します。
わかりやすくするために、チャネルの型を実際の構造ではなく int に変更しました。そして、長い処理を time.Sleep()
に置き換えました。
このコードが最後の for
でスタックしないように、すべてのタスク結果が返送された後、 ProducedResults
を閉じるにはどうすればよいですか?
quantityOfTasks:= 100 quantityOfWorkers:= 60 remainingTasks := make(chan int) producedResults := make(chan int) // produce tasks go func() { for i := 0; i < quantityOfTasks; i++ { remainingTasks <- 1 } close(remainingTasks) }() // produce workers for i := 0; i < quantityOfWorkers; i++ { go func() { for taskSize := range remainingTasks { // simulate a long task time.Sleep(time.Second * time.Duration(taskSize)) // return the result of the long task producedResults <- taskSize } }() } // read the results of the tasks and agregate them executedTasks := 0 for resultOfTheTask := range producedResults { //this loop will never finish because producedResults never gets closed // consolidate the results of the tasks executedTasks += resultOfTheTask }
チャネルに書き込みを行っているすべてのゴルーチンが戻ったら、チャネルを閉じる必要があります。 WaitGroup を使用すると、次のことを実現できます:
リーリー以上がすべての作業が完了したときに、複数のゴルーチンで満たされたチャネルを閉じるにはどうすればよいでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。