小编典典

所有goroutine完成后,让golang关闭使用的频道

go

我正在尝试运行许多goroutine,这些例程会将其结果提供给某个渠道。我需要一种好的方法来在所有goroutine完成后让通道关闭。

我的第一个尝试是在产生所有go例程之后关闭它,但是我认为以某种方式在所有goroutine可以发送结果之前关闭通道。

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循环之前运行,则此方法将不起作用。

有没有更好的办法?


阅读 193

收藏
2020-07-02

共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...)
}
2020-07-02