【问题标题】:Let golang close used channel after all goroutines finished在所有 goroutine 完成后让 golang 关闭使用的通道
【发布时间】:2014-03-16 04:34:40
【问题描述】:

我正在尝试运行一些 goroutine,它们会将它们的结果提供给通道。在所有 goroutine 完成后,我需要一种让通道关闭的好方法。

我的第一次尝试是在生成所有 goroutines 之后关闭它,但我认为通道在所有 goroutines 可以发送它们的结果之前以某种方式关闭。

for i:=0; i<=10;i++{
  go func(){
    result:=calculate()
    c<-result
  }()
}
close(c)
for result:= range c{
  all_result=append(all_result, result...)
}

然后,我第二次尝试计算一个线程并在没有线程运行后关闭它。

for i:=0; i<=10;i++{
  go func(){
    atomic.AddUint64(&go_routine_count, 1)
    result:=calculate()
    c<-result
    atomic.AddUint64(&rt_count, ^uint64(0))
  }()
}
go func(){
  for{
    // some little time to let above goroutine count up go_routine_count before this goroutine can actually check go_routine_count==0
    time.Sleep(time.Millisecond)
    go_current_routine_count:=atomic.LoadUint64(&go_routine_count)
    if go_routine_count==0{
      close(c)
    }
  }
}()
for result:= range c{
  all_result=append(all_result, result...)
}

它有效,但我觉得可能有更正确或更有效的方法。另外,在某些情况下,如果后面的用于计数检查的 goroutine 在循环中的 goroutines 之前运行,则此方法将不起作用。

有没有更好的方法?

【问题讨论】:

    标签: go goroutine


    【解决方案1】:

    sync.WaitGroup 类型应该封装您想要做的事情,而不需要睡眠呼叫或忙于等待。它允许您等待任意数量的任务,而不必担心它们完成的顺序。

    以您的原始示例为例,您可以将其更改为使用等待组,如下所示:

    var wg sync.WaitGroup
    for i:=0; i<=10;i++{
        wg.Add(1)
        go func(){
            result:=calculate()
            c<-result
            wg.Done()
        }()
    }
    // Close the channel when all goroutines are finished
    go func() {
        wg.Wait()
        close(c)
    }()
    for result:= range c{
        all_result=append(all_result, result...)
    }
    

    【讨论】:

    • 感谢您提供好的解决方案。我想知道如果我使用它,我是否真的需要后一个 goroutine 来关闭通道。所以,我只尝试了wg.Wait(); close(c) 没有 goroutine,它给了我一个死锁错误。这是为什么呢?
    • 您的 goroutine 将被阻止尝试写入通道 c,直到在最后的 for 循环中开始读取值。 wg.Wait() 呼叫也将被阻止,因为它正在等待 wg.Done() 呼叫。所以在这种情况下你确实需要额外的 goroutine。
    • 谢谢!我完全明白了。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-17
    • 2018-04-09
    • 2019-06-27
    • 2023-04-03
    • 1970-01-01
    • 2017-02-14
    • 1970-01-01
    相关资源
    最近更新 更多