为什么会陷入僵局呢?

我在 Go Playground 中运行此代码:https ://play.golang.org/p/1gqgXZXDhsF但它以死锁结束:


package main


import (

    "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”,然后尝试将该数据发送到记录器通道。


我对频道还很陌生。我了解什么是死锁以及可能发生死锁的某些情况,尤其是在使用无缓冲通道时。但这在我看来应该有效。


在此先感谢您的帮助。


慕村9548890
浏览 125回答 1
1回答

慕码人8056858

createFakeReadData正在无休止地将字符串发送到像rChanMap[5].&nbsp;但log你只从输出通道接收一次:func&nbsp;log(l&nbsp;<-chan&nbsp;string)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;fmt.Println(<-l) }由于您创建的所有通道都是无缓冲的,如果没有 goroutine 从输出通道接收数据logChan,其他 goroutine 将永远阻止尝试发送给它。您可能希望将log函数更改为:func&nbsp;log(l&nbsp;<-chan&nbsp;string)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;m&nbsp;:=&nbsp;range&nbsp;l&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fmt.Println(m) &nbsp;&nbsp;&nbsp;&nbsp;} }这样它就会从通道接收信息,直到通道关闭为止。顺便说一句,一些免费建议:string(n)不将整数转换为字符串,尝试搜索正确的方法来执行此操作当您创建通道时,您应该考虑何时应该关闭它,在您的代码中没有通道被关闭详细了解缓冲通道和非缓冲通道之间的区别
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go