gpt4 book ai didi

go - 如何在处理结果时正确关闭 Goroutines 中的共享 channel

转载 作者:行者123 更新时间:2023-12-02 23:35:56 27 4
gpt4 key购买 nike

我正在尝试找到使用工作程序 go 例程生成的结果的正确方法,同时在所有工作完成后优雅地退出结果循环。为了说明这一点,我做了以下例子。我的真实情况与此示例略有不同,因为我不知道每个工作程序 go 例程将返回多少“工作”,显然这些 for 循环正在执行固定数量的结果 (5)。

我对 goroutine 和 channel 很陌生,但以下是我所理解的基本租户;

  • 只有发件人才能关闭 channel
  • 在 channel 上执行 range 将继续,直到 channel 关闭
package main

import (
"fmt"
"sync"
)

func worker1(r chan string, wg *sync.WaitGroup) {
for i := 0; i < 5; i++ {
r <- fmt.Sprintf("1.%d", i)
}

wg.Done()
}

func worker2(r chan string, wg *sync.WaitGroup) {
for i := 0; i < 5; i++ {
r <- fmt.Sprintf("2.%d", i)
}

wg.Done()
}

func main() {
var wg sync.WaitGroup

r := make(chan string)
wg.Add(2)
go worker1(r, &wg)
go worker2(r, &wg)

for i := range r {
fmt.Printf("Got job result: %s\n", i)
}

wg.Wait()
}

这个例子是死锁的,因为范围循环永远不会退出,因为 channel 永远不会关闭。工作完成后,我可以在 channel 上执行关闭操作(即将 wg.Done() 替换为 close(r)),但是当其他工作协程尝试将进一步的结果发送到已经关闭的 channel 。

最后我想我可以将 wg.Wait() 移动到结果循环上方,完成后关闭 channel ,然后开始打印结果,但这意味着我无法打印任何结果直到所有线程上的所有工作都完成为止。

所有工作线程完成后优雅地退出结果循环,同时也不等到所有工作完成才开始打印结果的正确方法是什么?

最佳答案

我已经编辑了您的代码,使其可以无死锁地工作。问题在于 channel 上的接收阻塞了主线程,并且两个 goroutines 都不再发送任何数据。

此解决方案运行一个新的 goroutine,一旦 WaitGroup 完成,它就会关闭结果 channel 。

package main

import (
"fmt"
"sync"
)

func worker1(r chan string, wg *sync.WaitGroup) {
for i := 0; i < 5; i++ {
r <- fmt.Sprintf("1.%d", i)
}

wg.Done()
}

func worker2(r chan string, wg *sync.WaitGroup) {
for i := 0; i < 5; i++ {
r <- fmt.Sprintf("2.%d", i)
}

wg.Done()
}

func main() {
var wg sync.WaitGroup

r := make(chan string)
wg.Add(2)
go worker1(r, &wg)
go worker2(r, &wg)

go func() {
defer close(r)
wg.Wait()
}()

for i := range r {
fmt.Printf("Got job result: %s\n", i)
}
}

(Go Playground)

关于go - 如何在处理结果时正确关闭 Goroutines 中的共享 channel ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59018372/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com