【问题标题】:throw: all goroutines are asleep - deadlockthrow:所有 goroutine 都处于休眠状态 - 死锁
【发布时间】:2012-09-06 01:47:19
【问题描述】:

给定以下简单的 Go 程序

package main

import (
    "fmt"
)

func total(ch chan int) {
    res := 0
    for iter := range ch {
        res += iter
    }
    ch <- res
}

func main() {
    ch := make(chan int)
    go total(ch)
    ch <- 1
    ch <- 2
    ch <- 3
    fmt.Println("Total is ", <-ch)
}

我想知道是否有人可以告诉我为什么我会得到

throw: all goroutines are asleep - deadlock!

谢谢

【问题讨论】:

    标签: multithreading go deadlock channel


    【解决方案1】:

    由于您永远不会关闭 ch 频道,因此范围循环将永远不会结束。

    您不能在同一频道上发回结果。一种解决方案是使用不同的解决方案。

    你的程序可以这样调整:

    package main
    
    import (
        "fmt"
    )
    
    func total(in chan int, out chan int) {
        res := 0
        for iter := range in {
            res += iter
        }
        out <- res // sends back the result
    }
    
    func main() {
        ch := make(chan int)
        rch  := make(chan int)
        go total(ch, rch)
        ch <- 1
        ch <- 2
        ch <- 3
        close (ch) // this will end the loop in the total function
        result := <- rch // waits for total to give the result
        fmt.Println("Total is ", result)
    }
    

    【讨论】:

    • 与问题没有直接关系,但理解goroutines仍然很有趣:如果你在out &lt;- res之后添加fmt.Println("Exiting total")你可能永远看不到它,因为程序可能会更快退出,而无需等待goroutines 来完成。
    • 我几天前开始学习Go,我不明白为什么 res := 0 只运行一次?整个功能不应该运行3次吗?在您的示例中,只有循环运行了 3 次。
    • @OybekToirov 整个函数只运行一次,每次 int inchannel 中有东西时迭代进行
    • 这只有在您知道rch 频道中有多少个结果时才有效,如果您有未知的更多工作数会怎样?不使用等待组,你怎么能做到呢?
    • 你不想在func签名中指定每个通道是读还是写吗?
    【解决方案2】:

    这也是对的。

    package main
    
    import "fmt"
    
    func main() {
        c := make(chan int)
        go do(c)
        c <- 1
        c <- 2
        // close(c)
        fmt.Println("Total is ", <-c)
    }
    
    func do(c chan int) {
        res := 0
        // for v := range c {
        //  res = res + v
        // }
        for i := 0; i < 2; i++ {
            res += <-c
        }
        c <- res
        fmt.Println("something")
    }
    

    【讨论】:

    • 这并没有回答原始程序出了什么问题的问题。
    猜你喜欢
    • 2013-11-22
    • 2021-04-05
    • 1970-01-01
    • 2015-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-11
    • 1970-01-01
    相关资源
    最近更新 更多