为了账号安全,请及时绑定邮箱和手机立即绑定

为什么会陷入僵局呢?

为什么会陷入僵局呢?

Go
慕村9548890 2023-08-14 15:03:54
我在 Go Playground 中运行此代码:https ://play.golang.org/p/1gqgXZXDhsF但它以死锁结束:package mainimport (    "fmt"    "time")func createFakeReadData(r map[int]chan string, n int) {    for {        time.Sleep(time.Duration(n - 1) * time.Second)        r[n] <- string(n)    }}func log(l <-chan string) {    fmt.Println(<-l)}func main() {    logChan := make(chan string)    go log(logChan)    rChanMap := make(map[int]chan string)    rChanMap[5] = make(chan string)    rChanMap[6] = make(chan string)    rChanMap[7] = make(chan string)    rChanMap[8] = make(chan string)    go createFakeReadData(rChanMap, 5)    go createFakeReadData(rChanMap, 6)    go createFakeReadData(rChanMap, 7)    go createFakeReadData(rChanMap, 8)    for {        var f string        select {        case f = <-rChanMap[5]:            logChan <- f        case f = <-rChanMap[6]:            logChan <- f        case f = <-rChanMap[7]:            logChan <- f        case f = <-rChanMap[8]:            logChan <- f        }    }}fatal error: all goroutines are asleep - deadlock!我有 5 个 goroutine 和一个 main 中的 select 语句,它控制其中的 4 个(读取器)。第 5 个(记录器)只是坐着等待通道上发送给它的任何内容。当 4 个读取器之一从通道获取输入时,它应该触发 select 语句中的“case”,然后尝试将该数据发送到记录器通道。我对频道还很陌生。我了解什么是死锁以及可能发生死锁的某些情况,尤其是在使用无缓冲通道时。但这在我看来应该有效。在此先感谢您的帮助。
查看完整描述

1 回答

?
慕码人8056858

TA贡献1803条经验 获得超6个赞

createFakeReadData正在无休止地将字符串发送到像rChanMap[5]. 但log你只从输出通道接收一次:

func log(l <-chan string) {
    fmt.Println(<-l)
}

由于您创建的所有通道都是无缓冲的,如果没有 goroutine 从输出通道接收数据logChan,其他 goroutine 将永远阻止尝试发送给它。

您可能希望将log函数更改为:

func log(l <-chan string) {
    for m := range l {
        fmt.Println(m)
    }
}

这样它就会从通道接收信息,直到通道关闭为止。

顺便说一句,一些免费建议:

  1. string(n)不将整数转换为字符串,尝试搜索正确的方法来执行此操作

  2. 当您创建通道时,您应该考虑何时应该关闭它,在您的代码中没有通道被关闭

  3. 详细了解缓冲通道和非缓冲通道之间的区别


查看完整回答
反对 回复 2023-08-14
  • 1 回答
  • 0 关注
  • 124 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信