英文:
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 <- 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
}
I don't understand why I'm getting the error fatal error: all goroutines are asleep - deadlock!
on the line readyQueue <- 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论