go - 具有多个 channel 的多个 goroutine 的死锁

标签 go channel goroutine

我正在开发一个示例程序,使用具有多个 channel 的 goroutine 打印 1 到 100 之间的奇数之和和偶数之和。

你可以找到我的代码

here

输出

sum of even number = 2550
sum of odd number = 2500
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.print(0x434100, 0x11db7c)
    /tmp/sandbox052575152/main.go:18 +0xc0
main.main()
    /tmp/sandbox052575152/main.go:14 +0x120

该代码有效但存在死锁。 我不确定我的代码有什么问题

最佳答案

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

func print(sumValues <-chan string ){
    for val := range sumValues {
        fmt.Println(val)
    }
}

所以你必须在 doSum 函数中的所有 go 例程完成后关闭 doSum 函数中的 sum channel (否则 sum channel 可能在 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)
}

关于go - 具有多个 channel 的多个 goroutine 的死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53148676/

相关文章:

go - 发出所有goroutine后如何使用goroutine按顺序打印数字

go - 为什么局部变量在goroutine中的匿名函数中是不同的参数

mysql - goroutine 中的数据库调用失败而没有错误

go - byte[] channel 使用

go - Go中限制并发的简单方法

go - 写入两个独立的 channel 是否可靠地顺序进行?

go - Go 中令人尴尬的并行任务的惯用解决方案是什么?

go - 这个 Go print 语句的顺序是什么?

go - 在 Gin Framework 中开发的 REST API 的文件夹结构和包命名约定

mysql - Go Template 循环(范围)出评论