【问题标题】:How can I have a single goroutine function that waits for values from multiple others?我怎样才能拥有一个等待来自多个其他人的值的 goroutine 函数?
【发布时间】:2020-05-31 19:00:33
【问题描述】:

我创建了一个 Go playground sample 来说明我在说什么。

在示例中,我创建了一个 goroutine,func2,我只想等待通过其通道的输入并在它到达后打印值。

func func2(ch chan int) {
    fmt.Println("func2")
    v:=<-ch
    fmt.Println(v)
}

然后,在一个循环中,我为另一个函数创建 goroutine,它们是 WaitGroup 的一部分。

func func1(ch chan int, wg *sync.WaitGroup) {
    fmt.Println("func1")
    ch <- 11032
    wg.Done()
}

在主程序中,我等待 WaitGroup。我遇到了僵局,我不知道如何解决它。很清楚我想要实现的目标,我希望 func2 在我调用它后作为线程保持打开状态,以处理 n 个值,其中 n 是我为 func1 调用的 goroutine 的数量。我考虑在 func2 中使用 WaitGroup Wait,但我不希望它阻塞,因为它需要在 func1 发送时处理新数据。

【问题讨论】:

  • 让 func2 range 超过 ch 直到关闭。

标签: multithreading go deadlock channel goroutine


【解决方案1】:

我认为您遇到了僵局,因为您的 func2 仅消耗来自 ch1 值,然后完成。然后其他的func1 goroutines 卡在等待ch 可以写入,他们不能这样做,因为没有其他 goroutine 可以从另一端的ch 读取。

由于您希望func2 持续使用来自ch 的值,直到ch 关闭,您需要在func2 中创建一个循环,如下所示:

func func2(ch chan int) {
    fmt.Println("func2")
    for v := range ch {
        fmt.Println(v)
    }
}

这将使func2“活着”并从ch读取,直到您在其他地方执行close(ch)。在您的示例中,关闭ch 的适当位置可能是在wg.Wait() 之后的main

如果你想确保在程序结束之前看到所有Println 语句的结果,你还应该使用一些同步机制来等待func2 结束。否则main 将在close(ch) 之后立即结束,这可能会或可能不会func2 打印它收到的每个值之前。

对此的一种常用技术是“完成”通道。例如:

func func2(ch chan int, done chan bool) {
    fmt.Println("func2")
    for v := range ch {
        fmt.Println(v)
    }
    done <- true
}

main:

done := make(chan bool)
go func2(ch, done)
...
wg.Wait()
close(ch)
<-done

使用chan struct{}(空结构)也很常见,因为空结构不需要内存。

【讨论】:

    【解决方案2】:

    您正在寻找的是一种在所有值都完成流式传输时关闭通道的干净方法。当新值出现时,您可以创建一个新通道并开始在此流式传输值。我就是这样做的,也许有帮助

    var wg sync.WaitGroup
    
    toUpdate := make(chan *someType, BufferSize)
    
    for i := 0; i < BufferSize; i++ {
        go processEvents(toUpdate, &wg)
    }
    
    // // wait till all the checks have come back
    go func(toUpdate chan * someType, group *sync.WaitGroup) {
        group.Wait()
        close(toCreate)
    }(toCreate, toUpdate, &wg)
    

    【讨论】:

      猜你喜欢
      • 2019-10-30
      • 2021-01-10
      • 2019-07-18
      • 2011-09-22
      • 1970-01-01
      • 1970-01-01
      • 2020-06-04
      • 1970-01-01
      • 2021-10-06
      相关资源
      最近更新 更多