为了账号安全,请及时绑定邮箱和手机立即绑定

一个通道有一个接收者和未知数量的 goroutines 发送者导致死锁

一个通道有一个接收者和未知数量的 goroutines 发送者导致死锁

Go
慕侠2389804 2023-06-01 14:59:13
我有一个频道,接收器是主要的。我生成了多个 goroutine,每个 goroutine 通过通道发送一个字符串。现在,这会导致死锁,因为我没有使用 close 函数正确关闭通道。问题是,我不知道将创建多少 goroutines,因此无法知道何时关闭通道。我试过使用 WaitGroup,问题是,我读到我不能在 goroutine 中使用 Add,我应该在主进程/goroutine 中使用 wg.Add(1),我试过使用 Add in父 goroutine 产生子 goroutine,这也导致了死锁包主import (    "fmt"    "sync")var i = 0func doSomething(ch chan string, wg sync.WaitGroup) {    defer wg.Done()    ch <- fmt.Sprintf("doSomething: %d", i)    i++    if i == 10 {return}    wg.Add(1)    go doSomething(ch, wg)}func main() {    ch := make(chan string)    var wg sync.WaitGroup    wg.Add(1)    go doSomething(ch, wg)    wg.Wait()    for s := range ch {        fmt.Println(s)    }}现在,这只是一个测试代码,所以,假设我们不知道我们将只创建 10 个 goroutines,假设它在运行时是未知的,如果我不使用,我会立即得到一个没有任何输出的死锁错误WorkGroup 我在打印第 10 个字符串之前收到错误(因为我没有关闭通道)我还尝试过不为每个函数调用生成一个 goroutine,而是对所有递归调用(从 main 开始)使用一个 goroutine,并关闭通道,我为 go 创建了一个匿名函数,它首先调用 doSomething 函数然后调用关闭,所以所有的递归调用都会被评估,我们肯定知道什么时候关闭通道。但是,这就是我现在想要完成的,我试图让未知数量的 goroutine 一起工作,并在它们以某种方式完成后关闭通道。
查看完整描述

1 回答

?
萧十郎

TA贡献1815条经验 获得超12个赞

有几个问题。


第一个是程序在将它们作为参数传递时复制等待组值。复制时等待组不能正常工作。而是将指针传递给等待组。


第二个问题是 main 在从通道接收值之前等待所有 goroutines 完成。因为通道的缓冲区不够大,无法容纳所有发送的值,所以程序会死锁。


第三个问题是通道上方的主要范围,但没有任何东西关闭通道。Main 不会因此退出。


要解决第二个和第三个问题,请启动另一个 goroutine 等待doSomthings 并在完成后关闭通道。


尝试这个:


func doSomething(ch chan string, wg *sync.WaitGroup) {

    defer wg.Done()

    ch <- fmt.Sprintf("doSomething: %d", i)

    i++

    if i == 10 {

        return

    }

    wg.Add(1)

    go doSomething(ch, wg)

}


func main() {

    ch := make(chan string)

    var wg sync.WaitGroup

    wg.Add(1)

    go doSomething(ch, &wg)

    go func() {

        wg.Wait()

        close(ch)

    }()

    for s := range ch {

        fmt.Println(s)

    }

}


查看完整回答
反对 回复 2023-06-01
  • 1 回答
  • 0 关注
  • 96 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信