【问题标题】:Sync.WaitGroup, why closer in a goroutineSync.WaitGroup,为什么在 goroutine 中更接近
【发布时间】:2016-01-15 19:52:12
【问题描述】:

以下是 Go 编程书中的示例代码。我不明白为什么 close 需要是它自己的 goroutine。我试图将 closer 移到 main 中,但它崩溃了。有人可以解释为什么关闭程序需要在一个单独的 goroutine 中?

谢谢!

func makeThumbnails(filenames <-chan string, result chan<- int64) int64 {
  sizes := make(chan int64)
  var wg sync.WaitGroup
  for f := range filenames {
      wg.Add(1)
      go func(f string) {
        defer wg.Done()
        sizes <- int64(len(f))
      }(f)
  }

  // **closer**, why this guy needs to be in a goroutine???
  go func() {
    wg.Wait()
    close(sizes)
  }()

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

【问题讨论】:

    标签: go goroutine


    【解决方案1】:

    问题在于sizes 不是缓冲的chan,因此在需要读取sizes 之前,只有一个匿名goroutines 可以实际完成。这使得wg.Wait() 永远等待(因为下一个goroutine 阻塞sizes &lt;- 并且不能defer wg.Done())和死锁。

    通过将关闭器放入单独的 goroutine 中,它可以随时关闭 sizes chan,并在其间从 sizes 处理。归根结底,这是对 goroutine 的一个很好的使用——触发并忘记关闭!

    要使这段代码在没有更接近的 goroutine 的情况下工作,您可以简单地将 sizes 初始化为缓冲 chan,其缓冲区 >= filenames 的长度。

    func makeThumbnails(filenames <-chan string, result chan<- int64) int64 {
        sizes := make(chan int64, 10) // buffered channel, now!
        // if filenames sends more than 10 strings, though, we're in trouble!!
    
        var wg sync.WaitGroup
        for f := range filenames {
            wg.Add(1)
            go func(f string) {
                defer wg.Done()
                sizes <- int64(len(f))
            }(f)
        }
    
        // **closer**, this guy doesn't need to be a goroutine!!
        wg.Wait()
        close(sizes)
    
        var total int64
        for size := range sizes {
            total += size
        }
        result <- total
        return total
    }
    

    但是,由于filenames 的长度在运行时是不可知的,因此不可能轻易做到这一点。您必须通读filenames,将其存储到一个切片中,然后在range filenamesSlice 上初始化大小和for 和....是的,基本上您那时刚刚重写了整个函数。

    【讨论】:

      猜你喜欢
      • 2015-07-05
      • 1970-01-01
      • 2017-08-27
      • 1970-01-01
      • 2017-07-17
      • 1970-01-01
      • 2017-12-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多