【问题标题】:Deadlock with Multiple goroutines with multiple channels具有多个通道的多个 goroutine 的死锁
【发布时间】:2019-04-08 11:24:15
【问题描述】:

我正在开发一个示例程序,以使用具有多个通道的 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

代码可以工作,但会出现死锁。 我不确定我的代码有什么问题

【问题讨论】:

    标签: go channel goroutine


    【解决方案1】:

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

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

    所以你必须在 doSum 函数中的所有 goroutine 完成后关闭 doSum 函数中的 sum 通道(否则 sum 通道可能在 goroutine 完成之前关闭)。你可以使用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)
    }
    

    【讨论】:

    • 应该在哪里关闭sum 频道?在doSum 函数的末尾?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-20
    • 2020-08-02
    • 1970-01-01
    • 2018-09-10
    • 2019-05-04
    • 2018-10-23
    • 1970-01-01
    相关资源
    最近更新 更多