【问题标题】:golang sync.WaitGroup never finishesgolang sync.WaitGroup 永远不会完成
【发布时间】:2017-03-13 16:26:56
【问题描述】:

下面的代码从通道中获取worker并执行函数“call”,所有例程都完成并打印它们已完成但等待永远不会完成, 我通过使变量计数器在添加到 wg 时增加并在完成时减少并且在 for 循环结束时为零来跟踪 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)
}

【问题讨论】:

  • 我不明白你的代码,但我猜这个频道正在阻塞 goroutine。如果你把东西放在一个无缓冲的通道中,goroutine 会等待,直到接收器从通道中获取数据。在您的情况下,您的例程阻塞在 register &lt;- worker 并且永远不会调用 defer wg.Done()。
  • 非常感谢当我在 goroutine 中添加寄存器 时问题解决了
  • @apxp 请将您的评论作为答案发布,以便我们可以接受并且该问题将被视为已回答。

标签: go


【解决方案1】:

频道阻塞了你的 goroutine。如果您将一些数据放入无缓冲通道,goroutine 会等待,直到接收器从通道中获取数据。在您的情况下,您的例程块在 register &lt;- workerdefer wg.Done() 永远不会被调用,因为该函数正在等待。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多