我是 golang 的新手,我正在阅读 gopl 一书中的例子。

有一个并行制作缩略图的例子:

func makeThumbnails6(filenames <-chan string) int64 {
    sizes := make(chan int64)
    var wg sync.WaitGroup // number of working goroutines
    for f := range filenames {
        wg.Add(1)
        // worker
        go func(f string) {
            defer wg.Done()
            thumb, err := thumbnail.ImageFile(f)
            if err != nil {
                log.Println(err)
                return
            }
            info, _ := os.Stat(thumb) // OK to ignore error
            sizes <- info.Size()
        }(f)
    }

    // closer
    go func() {
        wg.Wait()
        close(sizes)
    }()

    var total int64
    for size := range sizes {
        total += size
    }
    return total
}

我的疑问是,在处理所有文件之前,是否有可能通过 wg.Wait()

例如,如果 work1 完成它的工作并将 wg 减少到零,那么就会发生一些神奇的调度并且 close 有时间运行并关闭 channel ?

任何帮助表示赞赏!

最佳答案

wg.Wait 在所有工作程序 goroutine 完成之前不会返回。当在更接近的 goroutine 中调用 wg.Wait 时,您已经为每个工作 goroutine 调用了 wg.Add(1) 一次,因此 wg.Wait 不会返回,直到 wg.Done 被调用相同的次数,当 goroutine 函数返回时就会发生这种情况。因此,在所有工作 goroutine 完成他们正在做的事情之前,较近的 goroutine 不会调用 close

正如您所说,理论上有可能 wg 的计数器可能在创建工作线程的循环中达到 0,但是一旦循环完成,所有 goroutine 完成后计数器才会为 0。由于在循环完成之前您不会启动更接近的 goroutine,因此在所有工作程序完成之前 wg.Wait 没有返回的危险。

关于go - 并行循环,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51006918/

10-11 07:44