【问题标题】:go routine channel & WaitGroup fatal error: all goroutines are asleep - deadlockgoroutine channel & WaitGroup 致命错误:所有 goroutines 都处于睡眠状态 - 死锁
【发布时间】:2019-11-03 23:13:07
【问题描述】:

有人可以解释为什么我在将回复推送到没有指示缓冲区大小的通道时遇到死锁吗?

当我以这种方式创建确认通道时,我的测试陷入僵局;
这一个死锁:deadlock

   request := RequestMessage{
        Value:   "make it rain",
        Confirm: make(chan *ReplyMessage),
    }

但不是在我这样创建的时候;
这个不死锁:no deadlock

    request := RequestMessage{
        Value:   "make it rain",
        Confirm: make(chan *ReplyMessage,1),
    }
package main

import (
    "fmt"
    "sync"
)

type ReplyMessage struct {
    Value string
}

type RequestMessage struct {
    Value   string
    Confirm chan *ReplyMessage
}

var requestChannel chan *RequestMessage

func main() {
    requestChannel = make(chan *RequestMessage, 10) // 8 is channel buffer size
    request := RequestMessage{
        Value:   "make it rain",
        Confirm: make(chan *ReplyMessage),
    }
    requestChannel <- &request

    var wg sync.WaitGroup
    wg.Add(1)
    go func() {
        defer wg.Done() // invoke Done on the WaitGroup when finished
        request := <-requestChannel
        fmt.Printf("Got Request: %s\n", request.Value)
        reply := ReplyMessage{Value: "hi"}
        request.Confirm <- &reply

    }()

    wg.Wait()

    reply := <-request.Confirm
    fmt.Println(reply.Value)
}

【问题讨论】:

    标签: go channel


    【解决方案1】:

    在无缓冲确认通道的情况下,您会遇到死锁,因为没有读取器,因此发送操作会阻塞。同时,您正在等待 goroutine 在 main 中返回(wg.Wait() 语句)。所以 main 和 goroutine 都被阻塞了。

    使用缓冲的 chan 允许 goroutine 完成发送操作并退出,因此 wg.Wait() 语句成功并且此后 main 继续。

    解决无缓冲 chan 情况的一种方法是更改​​等待 goroutine 完成的位置,即

    reply := <-request.Confirm
    fmt.Println(reply.Value)
    wg.Wait()
    

    在阻塞 main 之前从 chan 读取时不会死锁,从而允许 goroutine 退出。

    【讨论】:

    • 非常有意义。在我的一项测试中,我生成了 100 个 go 例程。执行 wg.Wait() 非常适合该测试,然后我会遍历所有存储的确认通道。你的两种方法都有效。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2016-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-02
    • 2014-04-22
    • 1970-01-01
    相关资源
    最近更新 更多