如何让单个 goroutine 函数等待来自多个其他函数的值?



我创建了一个 Go 游乐场示例来说明我在说什么。

在示例中,我创建了一个 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()
}

总的来说,我等待候补组。我遇到了死锁,我不知道如何解决它。为了清楚我想要实现的目标,我希望func2在我调用它后保持打开状态,以处理n个值,其中n是我为func1调用的goroutine的数量。我考虑过在 func2 中使用 WaitGroup Wait,但我不希望它阻塞,因为它需要在发送时处理来自 func1 的新数据。

我认为您遇到了僵局,因为您的func2仅消耗了ch中的 1个值,然后完成。然后其他func1goroutines 被困在等待ch可以写入,他们无法做到这一点,因为没有其他 goroutine 可以从另一端的ch读取。

由于您希望func2chch关闭不断使用值,因此您需要在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{}(空结构(也很常见,因为空结构不需要内存。

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

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)

相关内容

最新更新