duanjuebiao6730 2016-11-04 13:06
浏览 57
已采纳

goroutine睡着了-死锁

In the following code I am trying to spawn MaxOutstanding number of handlers. Each handler loops over items in the queue queue and prints them out, I also write true to the done channel.

In my main function, I start the handlers and write 9 elements to the queue and wait for the 1st element to be written to the done queue.

package main


import "fmt"

type Request struct {
        int32
}
var MaxOutstanding = 5
func handle(queue chan *Request, i int, done chan bool) {
    for r := range queue {
        fmt.Println(i, "---", r)
        done <- true
    }
}

func Serve(clientRequests chan *Request, quit, done chan bool) {
    // Start handlers
    for i := 0; i < MaxOutstanding; i++ {
        go handle(clientRequests, i, done)
    }
    <-quit  // Wait to be told to exit.
}


func main() {
    clientRequests := make(chan *Request)
    quit := make(chan bool)
    done := make(chan bool)

    go Serve(clientRequests, quit, done)

    clientRequests <- &Request{4}
    clientRequests <- &Request{1}
    clientRequests <- &Request{2}
    clientRequests <- &Request{3}

    clientRequests <- &Request{5}
    clientRequests <- &Request{6}
    clientRequests <- &Request{7}
    clientRequests <- &Request{8}
    clientRequests <- &Request{9}
    fmt.Println( "...........>", <- done )
    close(clientRequests)
    close(done)
}

On execution I get the following error. I don't see whats wrong with the implementation, I am even closing the channel.

4 --- &{4}
0 --- &{1}
1 --- &{2}
2 --- &{3}
3 --- &{5}
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main()
        /home/ubuntu/digs-svc/src/digs/go1.go:45 +0x251

goroutine 5 [chan receive]:
main.Serve(0xc82004c060, 0xc82004c0c0, 0xc82004c120)
        /home/ubuntu/digs-svc/src/digs/go1.go:28 +0x92
created by main.main
        /home/ubuntu/digs-svc/src/digs/go1.go:37 +0xb9

goroutine 6 [chan send]:
main.handle(0xc82004c060, 0x0, 0xc82004c120)
        /home/ubuntu/digs-svc/src/digs/go1.go:16 +0x23b
created by main.Serve
        /home/ubuntu/digs-svc/src/digs/go1.go:25 +0x5b

EDIT:

Apparently, the fmt.Println("....", <- done) wasn't enough to signify that there is a consumer to the done channel. I moved the code up in the execution order. A consumer needs to be "listening" on the channel when data is written to it. In my earlier code, the when the first data was written there were no consumer.

Working code.

https://play.golang.org/p/98l2M4XO9t

  • 写回答

2条回答 默认 最新

  • driuwt9557 2016-11-04 13:20
    关注

    You're blocking the iteration over the channel in your handle function with the send on the done channel, because nothing is receiving on the other side.

    Those extra channels aren't really doing anything, and you could just add a WaitGroup to synchronize the handler's exit, then you can remove the done channel which will allow the handler to continue.

    func handle(queue chan *Request, i int, wg *sync.WaitGroup) {
        defer wg.Done()
    
        for r := range queue {
            fmt.Println(i, "---", r)
        }
    }
    
    func Serve(clientRequests chan *Request, wg *sync.WaitGroup) {
        // Start handlers
        for i := 0; i < MaxOutstanding; i++ {
            wg.Add(1)
            go handle(clientRequests, i, wg)
    
        }
    }
    
    func main() {
        clientRequests := make(chan *Request)
        var wg sync.WaitGroup
    
        go Serve(clientRequests, &wg)
    
        for i := int32(0); i < 50; i++ {
            clientRequests <- &Request{i}
        }
    
        close(clientRequests)
        wg.Wait()
    }
    

    https://play.golang.org/p/oUFjZONjhk (note that in the playground, this example seems to currently favor a single goroutine being the receiver. Normally the blocked goroutines will receive randomly, and you can see that behavior if you compile and run normally)

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥200 wsl2 vllm qwen1.5部署问题
  • ¥100 有偿求数字经济对经贸的影响机制的一个数学模型,弄不出来已经快要碎掉了
  • ¥15 这个公式写进SIMULINK中的function模块的代码中应该是什么样的
  • ¥15 javaweb登陆的网页为什么不能正确连接查询数据库
  • ¥15 数学建模数学建模需要
  • ¥15 已知许多点位,想通过高斯分布来随机选择固定数量的点位怎么改
  • ¥20 nao机器人语音识别问题
  • ¥15 怎么生成确定数目的泊松点过程
  • ¥15 layui数据表格多次重载的数据覆盖问题
  • ¥15 python点云生成mesh精度不够怎么办