Go语言为什么会出现“fatal error: all goroutines are asleep”导致死锁的情况?

huangapple go评论79阅读模式
英文:

Why does Go deadlock with "fatal error: all goroutines are asleep"

问题

以下是代码的翻译:

这是我代码中相关的摘录:

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 // 阻塞以保持主线程活动
}

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] ready队列中没有任何内容")
    }

    select {
    case p := <-waitQueue:
        fmt.Println(p)
    default:
        fmt.Println("[tick] wait队列中没有任何内容")
    }

    select {
    case p := <-runQueue:
        fmt.Println(p)
    default:
        fmt.Println("[tick] run队列中没有任何内容")
    }

    quit <- 0
}

我不明白为什么在上述代码中的readyQueue <- proc这一行会出现错误fatal error: all goroutines are asleep - deadlock!

英文:

Here's the relevant excerpt from my code:

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 &lt;- proc
tick(quit, readyQueue, runQueue, waitQueue)
case proc.Status == RUN:
runQueue &lt;- proc
tick(quit, readyQueue, runQueue, waitQueue)
case proc.Status == WAIT:
waitQueue &lt;- proc
tick(quit, readyQueue, runQueue, waitQueue)
}
}
&lt;-quit // blocks to keep main thread alive
}
func tick(quit chan int, readyQueue chan Proc, runQueue chan Proc, waitQueue chan Proc) {
select {
case p := &lt;-readyQueue:
fmt.Println(p)
default:
fmt.Println(&quot;[tick] nothing in ready queue&quot;)
}
select {
case p := &lt;-waitQueue:
fmt.Println(p)
default:
fmt.Println(&quot;[tick] nothing in wait queue&quot;)
}
select {
case p := &lt;-runQueue:
fmt.Println(p)
default:
fmt.Println(&quot;[tick] nothing in run queue&quot;)
}
quit &lt;- 0
}

I don't understand why I'm getting the error fatal error: all goroutines are asleep - deadlock! on the line readyQueue &lt;- proc in the above code.

答案1

得分: 14

根据代码显示,你没有为创建的任何通道启动并发读取器。因为它们是无缓冲的,对它们的任何写入操作都会阻塞,直到某个地方的其他端点读取。但在你的代码中并非如此。

如果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)

虽然这将解决你的即时问题,但你的设计仍然存在一些潜在问题。为了给出更全面的答案,我们需要确切地知道你想要实现什么。

英文:

As far as the code shows, you are never firing up a concurrent reader for any of the channels you create. Because they are unbuffered, any writes to them, will block until someone, somewhere reads from the other end. This is not the case in your code.

If tick is supposed to be the consumer, you should fire it up before going into the loop.
And it should then have a loop itself, so it keeps polling the channels for new values.

go tick(quit, readyQueue, runQueue, waitQueue)
for _, proc := range(procList) {
....
}

Another immediate solution would be to create all the channels with a buffer of 1.

quit := make(chan int, 1)
readyQueue := make(chan Proc, 1)
runQueue := make(chan Proc, 1)
waitQueue := make(chan Proc, 1)

While this will solve your immediate problem, there are still some other potential issues with your design. We would need to know exactly what it is you are trying to accomplish, in order to give a more well rounded answer.

huangapple
  • 本文由 发表于 2014年3月17日 09:14:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/22445378.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定