为什么这陷入僵局?

Dallin M .:

我正在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个(读取器)。第五个(记录器)只是坐在那里,等待任何东西通过通道发送给它。当4个读取器之一从某个通道获取输入时,它应该在select语句中触发一个“ case”,然后尝试将该数据继续发送到logger通道。

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

在此先感谢您的帮助。

satoru:

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. 了解有关缓冲和非缓冲通道之间差异的更多信息

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章