我正在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个goroutines和main中的select语句,它们控制其中的4个(读者)。第五名(记录器)只是坐在那里,等待任何东西要通过频道发送给它。当4个阅读器之一从某个通道获取输入时,它应该在select语句中触发一个“ case”,然后尝试将该数据继续发送到logger通道。
我是新来的频道。我了解死锁是什么以及可能发生死锁的某些情况,尤其是在使用无缓冲通道时。但是在我看来,这似乎应该可行。
感谢您的帮助。
createFakeReadData
不断向rChanMap[5]
之类的通道发送字符串。但是在log
中,您只能从输出通道接收一次:
func log(l <-chan string) {
fmt.Println(<-l)
}
由于您创建的所有通道都是未缓冲的,如果没有从输出通道logChan
接收到goroutine,则其他goroutine将永远阻止发送给它的尝试。
您可能想将log
功能更改为:
func log(l <-chan string) {
for m := range l {
fmt.Println(m)
}
}
这样,它将一直从频道接收直到关闭。