gpt4 book ai didi

go - Go 中的 channel 死锁

转载 作者:数据小太阳 更新时间:2023-10-29 03:14:06 26 4
gpt4 key购买 nike

我收到“ fatal error :所有 goroutines 都睡着了 - 死锁!“出于某种原因,在下面的代码中。我正在使用应该是非阻塞的缓冲 channel 。不确定我做错了什么

package main

import (
"fmt"
"sync"
)

func main() {
c := make(chan int, 2)
var wg sync.WaitGroup
wg.Add(2)

go doSomething(c, wg)
go doSomething(c, wg)
go doSomething(c, wg)

wg.Wait()

close(c)

for v := range c {
fmt.Print(v)
}

}

func doSomething(c chan<- int, wg sync.WaitGroup) {
defer wg.Done()
c <- 1

}

Playground 链接 https://play.golang.org/p/J9meD5aKna

最佳答案

虽然您的解决方案可能有效,但我对此并不满意。

首先,您需要更改 channel 大小才能使其正常工作这一事实表明存在潜在的问题/错误。现在,每次您想要启动另一个 doSomething 时,您都必须记住更改 channel 的长度。

其次,您等到所有 goroutine 完成后再从 channel 读取。这是一种“浪费”,因为 channel 范围循环的要点之一是您不必等到所有项目都生成(写入 channel ),您可以尽快开始处理项目他们已经准备好了。

所以我会把你的代码写成这样

func main() {
c := make(chan int)

var wg sync.WaitGroup
wg.Add(3)
go func() {
doSomething(c)
defer wg.Done()
}()
go func() {
doSomething(c)
defer wg.Done()
}()
go func() {
doSomething(c)
defer wg.Done()
}()

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

for v := range c {
fmt.Print(v)
}
}

func doSomething(c chan<- int) {
c <- 1
}

https://play.golang.org/p/T3dfiztKot

请注意 channel 的等待和关闭现在是如何在它自己的 goroutine 中进行的——这允许立即开始迭代 channel (现在是无缓冲的!)。

我还更改了代码,使 WaitGroup 永远不会离开声明它的范围(即它不用作参数),这是我个人的偏好。我相信它使代码更易于遵循和理解。

关于go - Go 中的 channel 死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42085173/

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