【问题标题】:How can we determine when the "last" worker process/thread is finished in Go?我们如何确定 Go 中“最后一个”工作进程/线程何时完成?
【发布时间】:2016-05-12 21:51:21
【问题描述】:

我将使用一个 hacky 低效的素数查找器来使这个问题更加具体。

假设我们的 main 函数触发了一堆“worker”goroutine。他们会将结果报告给打印它们的单个通道。但是不是每个工人都会报告一些事情,所以我们不能使用计数器来知道最后一个工作何时完成。或者有什么办法?

对于具体的例子,这里,main 触发 goroutine 来检查值 2...1000 是否是素数(是的,我知道它效率低下)。

package main

import (
    "fmt"
    "time"
)

func main() {
    c := make(chan int)
    go func () {
        for {
            fmt.Print(" ", <- c)
        }
    }()
    for n := 2; n < 1000; n++ {
        go printIfPrime(n, c)
    }
    time.Sleep(2 * time.Second)   // <---- THIS FEELS WRONG
}

func printIfPrime(n int, channel chan int) {
    for d := 2; d * d <= n; d++ {
        if n % d == 0 {
            return
        }
    }
    channel <- n
}

我的问题是我不知道如何在正确的时间可靠地停止它。我尝试在main 的末尾添加一个睡眠,它可以工作(但它可能需要太长时间,而且这不是编写并发代码的方法!)。我想知道是否有办法通过通道或其他方式发送停止信号,以便main 可以在正确的时间停止。

这里的诀窍是我不知道会有多少工人响应。

这是不可能的还是有什么很酷的技巧?

(如果这个主要示例有答案,那就太好了。我可能可以概括。或者可能没有。也许这是特定于应用程序的?)

【问题讨论】:

    标签: go concurrency


    【解决方案1】:

    使用WaitGroup

    以下代码使用两个 WaitGroup。主函数使用wgTest 等待print_if_prime 函数完成。完成后,它会关闭通道以中断打印 goroutine 中的 for 循环。主函数使用wgPrint等待打印完成。

    package main
    
    import (
      "fmt"
      "sync"
    ) 
    
    func main() {
      c := make(chan int)
      var wgPrint, wgTest sync.WaitGroup
    
      wgPrint.Add(1)
      go func(wg *sync.WaitGroup) {
        defer wg.Done()
        for n := range c {
            fmt.Print(" ", n)
        }
      }(&wgPrint)
    
      for n := 2; n < 1000; n++ {
        wgTest.Add(1)
        go print_if_prime(&wgTest, n, c)
      }
    
      wgTest.Wait()
      close(c)
      wgPrint.Wait()
    }
    
    func print_if_prime(wg *sync.WaitGroup, n int, channel chan int) {
      defer wg.Done()
      for d := 2; d*d <= n; d++ {
        if n%d == 0 {
            return
        }
      }
      channel <- n
    }
    

    playground example

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-10
      • 2015-07-09
      • 1970-01-01
      • 1970-01-01
      • 2017-09-09
      • 1970-01-01
      • 2016-01-31
      • 1970-01-01
      相关资源
      最近更新 更多