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

具有多个通道的多个 goroutine 的死锁

具有多个通道的多个 goroutine 的死锁

Go
翻阅古今 2023-05-08 14:27:31
我正在开发一个示例程序,使用具有多个通道的 goroutine 打印 1 到 100 之间的奇数和和偶数和。你可以找到我的代码这里输出sum of even number = 2550sum of odd number = 2500fatal error: all goroutines are asleep - deadlock!goroutine 1 [chan receive]:main.print(0x434100, 0x11db7c)    /tmp/sandbox052575152/main.go:18 +0xc0main.main()    /tmp/sandbox052575152/main.go:14 +0x120该代码有效但存在死锁。我不确定我的代码有什么问题
查看完整描述

1 回答

?
撒科打诨

TA贡献1934条经验 获得超2个赞

我们可以遍历通过通道发送的值。要打破这种迭代通道,需要明确关闭。否则 range 将以与 nil 通道相同的方式永远阻塞。在您的代码中,您没有关闭sum(打印功能sumValues通道)通道。这就是为什么以下功能将永远被阻止的原因。


func print(sumValues <-chan string ){

    for val := range sumValues {

        fmt.Println(val)

    }

}

所以你必须在函数sum中的doSum所有 go 例程doSum完成后关闭函数中的通道(否则sum通道可能会在 go 例程完成之前关闭)。你可以用sync.WaitGroup它来做到这一点。请参阅下面的更新doSum功能:


func doSum(sum chan<- string, oddChan <-chan int, evenChan <-chan int) {

    var waitGroup sync.WaitGroup


    waitGroup.Add(2) // Must wait for 2 calls to 'done' before moving on


    go func(sum chan<- string) {

        s1 := 0

        for val := range oddChan {

            s1 += val

        }

        sum <- fmt.Sprint("sum of odd number = ", s1)

        waitGroup.Done()

    }(sum)


    go func(sum chan<- string) {

        s1 := 0

        for val := range evenChan {

            s1 += val

        }

        sum <- fmt.Sprint("sum of even number = ", s1)

        waitGroup.Done()

    }(sum)


    // Waiting for all goroutines to exit

    waitGroup.Wait()


    // all goroutines are complete now close the sum channel

    close(sum)

}


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

添加回答

举报

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