私は、次のような小さなコードを書いて、Go の chan chan
構造を理解しようとしています。以下に、I 3 つのワーカー サブルーチンで 10 個のジョブを処理したいとします。各ワーカー サブルーチンには、処理対象の「ジョブ」を受け取る独自のチャネルがあります。 Go のメイン ルーチンは、チャネル プールからチャネルを取得することによって、ワーカー チャネルにジョブを配布します (したがって、chan chan
構造)。
しかし、このコードはデッドロック状況を引き起こします。このコードのいくつかのバリエーションを試してみましたが、同じエラーが発生しました。
ワーカー サブルーチンがチャネルからジョブを読み取るために永遠に待機するためでしょうか?それとも他の理由によるものですか (チャネルが途中で閉じられた可能性など)?全体の構造についての理解において、明らかに何かが欠けています。
誰かがこの問題とその解決方法を理解するのを手伝ってくれませんか?
プレイグラウンドからコードを取得し、要求に応じて以下にコピーします。
package main import ( "fmt" "sync" ) type Job struct { ID int } func worker(id int, jobs <-chan Job, wg *sync.WaitGroup) { defer wg.Done() fmt.Printf("Worker %d starting\n", id) for job := range jobs { fmt.Printf("Worker %d processing job %d\n", id, job.ID) } fmt.Printf("Worker %d done\n", id) } func main() { numWorkers := 3 maxJobs := 10 var wg sync.WaitGroup // Create the pool of worker channels pool := make(chan chan Job, numWorkers) for i := 0; i < numWorkers; i++ { workerChan := make(chan Job) // Create a new channel for each worker pool <- workerChan // Add the worker channel to the pool go worker(i, workerChan, &wg) } defer close(pool) // Create jobs and distribute them to workers for i := 0; i < maxJobs; i++ { job := Job{ID: i} wg.Add(1) workerChan := <-pool workerChan <- job } // Wait for all workers to complete wg.Wait() fmt.Println("All jobs are processed") }
まず第一に、ここには複数のチャネルは必要ありません。複数のワーカーに作業を分散するには、すべてのワーカーが単一の共有チャネルから読み取られるようにするだけです。作業内容をチャネルに送信するとき、使用可能なワーカーがあればそのうちの 1 人がそれを受信します。それ以外の場合、使用可能なワーカーが見つかるまでチャネル送信操作はブロックされます。
ワーカーごとに個別のチャネルを使用する場合でも、チャネルのチャネルは必要ありません。チャネルのサブセットだけが必要です。各従業員は専用チャネルから音声を聞き、あなたは自分の仕事の割り当てを管理します:
リーリーコードには 2 つの問題があります:
はブロックされます。どうしてもそのチャンネルのチャンネルを使用したい場合は、元に戻す必要があります:
は効果がありません。
pool のチャネルを閉じる必要があります。
以上がchan chan コンストラクトによりデッドロックが発生するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。