猿问

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

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


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在上面的代码。


繁花如伊
浏览 201回答 1
1回答

largeQ

就代码显示而言,您永远不会为您创建的任何频道启动并发阅读器。因为它们是无缓冲的,所以对它们的任何写入都会阻塞,直到有人在某处从另一端读取为止。在您的代码中并非如此。如果tick应该是消费者,你应该在进入循环之前启动它。然后它本身应该有一个循环,因此它会不断轮询通道以获取新值。go tick(quit, readyQueue, runQueue, waitQueue)for _, proc := range(procList) {&nbsp; &nbsp; ....}另一个直接的解决方案是创建缓冲区为 1 的所有通道。quit := make(chan int, 1)readyQueue := make(chan Proc, 1)runQueue := make(chan Proc, 1)waitQueue := make(chan Proc, 1)虽然这将解决您当前的问题,但您的设计仍然存在一些其他潜在问题。我们需要确切地知道您想要完成什么,以便给出更全面的答案。
随时随地看视频慕课网APP

相关分类

Go
我要回答