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

为什么 Go 会出现“致命错误:所有 goroutine 都睡着了”的死锁

为什么 Go 会出现“致命错误:所有 goroutine 都睡着了”的死锁

Go
繁花如伊 2021-07-28 17:14:11
这是我的代码的相关摘录:func main() {    quit := make(chan int)    readyQueue := make(chan Proc)    runQueue := make(chan Proc)    waitQueue := make(chan Proc)    procList := getInitialProcList()    fmt.Println(procList)    for _, proc := range(procList) {        switch {            case proc.Status == READY:                readyQueue <- proc                tick(quit, readyQueue, runQueue, waitQueue)            case proc.Status == RUN:                runQueue <- proc                tick(quit, readyQueue, runQueue, waitQueue)            case proc.Status == WAIT:                waitQueue <- proc                tick(quit, readyQueue, runQueue, waitQueue)        }    }    <-quit // blocks to keep main thread alive}func tick(quit chan int, readyQueue chan Proc, runQueue chan Proc, waitQueue chan Proc) {    select {    case p := <-readyQueue:        fmt.Println(p)    default:        fmt.Println("[tick] nothing in ready queue")    }    select {    case p := <-waitQueue:        fmt.Println(p)    default:        fmt.Println("[tick] nothing in wait queue")    }    select {    case p := <-runQueue:        fmt.Println(p)    default:        fmt.Println("[tick] nothing in run queue")    }    quit <- 0}我不明白为什么我得到的错误fatal error: all goroutines are asleep - deadlock!就行了readyQueue <- proc在上面的代码。
查看完整描述

1 回答

?
largeQ

TA贡献2039条经验 获得超7个赞

就代码显示而言,您永远不会为您创建的任何频道启动并发阅读器。因为它们是无缓冲的,所以对它们的任何写入都会阻塞,直到有人在某处从另一端读取为止。在您的代码中并非如此。


如果tick应该是消费者,你应该在进入循环之前启动它。然后它本身应该有一个循环,因此它会不断轮询通道以获取新值。


go tick(quit, readyQueue, runQueue, waitQueue)


for _, proc := range(procList) {

    ....

}

另一个直接的解决方案是创建缓冲区为 1 的所有通道。


quit := make(chan int, 1)


readyQueue := make(chan Proc, 1)

runQueue := make(chan Proc, 1)

waitQueue := make(chan Proc, 1)

虽然这将解决您当前的问题,但您的设计仍然存在一些其他潜在问题。我们需要确切地知道您想要完成什么,以便给出更全面的答案。


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

添加回答

举报

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