2017-03-12 9 views
1

チャネルからワーカーを取得して関数 "call"を実行する以下のコードは、すべてのルーチンが終了して終了しないというメッセージを出力します。 varitカウンタをインクリメントしてWaitGroupのカウンタをトレースしました完了したらWGとdecresingに追加すると、それはの終わりにゼロであったとき、ループ golang sync.WaitGroupは決して終了しません

package mapreduce 

import (
    "fmt" 
    "sync" 
) 

func schedule(jobName string, mapFiles []string, nReduce int, phase jobPhase, registerChan chan string) { 
    var ntasks int 
    var n_other int // number of inputs (for reduce) or outputs (for map) 
    switch phase { 
    case mapPhase: 
     ntasks = len(mapFiles) 
     n_other = nReduce 
    case reducePhase: 
     ntasks = nReduce 
     n_other = len(mapFiles) 

    } 

    fmt.Printf("Schedule: %v %v tasks (%d I/Os)\n", ntasks, phase, n_other) 
    var wg sync.WaitGroup 
    for i := 0; i < ntasks; i++ { 
     worker := <-registerChan 
     doTaskArg := DoTaskArgs{jobName, mapFiles[i], phase, i, n_other} 
     wg.Add(1) 
     go func() { 
      defer wg.Done() 

      done := call(worker, "Worker.DoTask", doTaskArg, nil) 
      if done { 
       registerChan <- worker 
      } else { 
       i = i - 1 
      } 

     }() 
    } 

    wg.Wait() 

    fmt.Printf("Schedule: %v phase done\n", phase) 
} 
+0

私はあなたのコードを理解していませんが、私はチャンネルがルーチンを止めていると思います。バッファされていないチャンネルに何かを入れると、ゴルーチンは受信者がチャンネルからデータを取得するまで待ちます。あなたの場合、ルーチンは 'register < - worker'でブロックし、wg.Done()を呼び出すことは決して呼び出されません。 – apxp

+0

ありがとうございました。私はレジスタ< - ワーカーをgoルーチンに追加すると多くの問題を解決しました。 – miro

+0

@apxpあなたのコメントを回答として投稿してください。受け入れられ、質問は回答とみなされます。 – mickmackusa

答えて

2

チャンネルはあなたのゴルーチンをブロックしてください任意の助け。バッファされていないチャネルにデータを入れると、受信者がチャネルからデータを取得するまでゴルーチンは待機します。あなたの場合、register <- workerdefer wg.Done()のルーチンブロックは、関数が待機しているので決して呼び出されません。

関連する問題