ホームページ  >  記事  >  バックエンド開発  >  すべての作業が完了したときに、複数のゴルーチンで満たされたチャネルを閉じるにはどうすればよいでしょうか?

すべての作業が完了したときに、複数のゴルーチンで満たされたチャネルを閉じるにはどうすればよいでしょうか?

WBOY
WBOY転載
2024-02-10 12:27:10792ブラウズ

当所有工作完成后,如何关闭由多个 goroutine 填充的通道?

すべての作業が完了したときに、複数のゴルーチンで満たされたチャネルをどのように閉じるかは、よく話題になる質問です。 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 サイトの他の関連記事を参照してください。

声明:
この記事はstackoverflow.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。