我对戈朗编程非常陌生,我有下面的程序来生成deadlock,我不明白为什么?
另一件事是,如果我关闭doAdd方法中的通道,然后进入无限循环,这对我来说也有点奇怪。
这是节目。
var wg sync.WaitGroup
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
ch3 := make(chan string)
chClose := make(chan bool)
wg.Add(3)
go doAdd(ch1, "ch1")
go doAdd(ch2, "ch2")
go doAdd(ch3, "ch3")
go waitForClose(chClose)
for {
select {
case x := <-ch1:
fmt.Println("Got from ch1 ", x)
case y := <-ch2:
fmt.Println("Got from ch2 ", y)
case z := <-ch3:
fmt.Println("Got from ch3 ", z)
case <-chClose:
fmt.Println("CLOSED")
break
}
}
}
func waitForClose(chClose chan bool) {
wg.Wait()
chClose <- true
}
func doAdd(ch chan string, name string) {
for i := 0; i < 10; i++ {
ch <- strconv.Itoa(i)
}
wg.Done()
}产出如下:
Got from ch1 0
Got from ch1 1
Got from ch1 2
Got from ch1 3
Got from ch1 4
Got from ch1 5
Got from ch1 6
Got from ch1 7
Got from ch1 8
Got from ch1 9
Got from ch2 0
Got from ch2 1
Got from ch2 2
Got from ch2 3
Got from ch2 4
Got from ch2 5
Got from ch2 6
Got from ch2 7
Got from ch2 8
Got from ch2 9
Got from ch3 0
Got from ch3 1
Got from ch3 2
Got from ch3 3
Got from ch3 4
Got from ch3 5
Got from ch3 6
Got from ch3 7
Got from ch3 8
Got from ch3 9
CLOSED
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [select]:
main.main()
c:/PraveenData/demo/go-work/main.go:29 +0x915
exit status 2发布于 2016-05-11 08:37:30
出现死锁的原因是,您的break中的select只从select中分离出来,使得for循环可以自由地重新输入select,在那里没有一个通道可以读取。
你可以这样做来拯救这一切:
done := false
for !done {
select {
...
case <-chClose:
done = true
fmt.Println("CLOSED")
}
}这在很小程度上允许for循环终止。
另一种方法是使用标签:
OuterLoop:
for {
select {
...
case <-chClose:
fmt.Println("CLOSED")
break OuterLoop
}
}在这种情况下,我个人对第一个版本略有偏爱,但这只是品味问题。
发布于 2016-05-11 08:34:31
程序末尾的break只会脱离select (并再次进入循环,从而导致死锁):用return替换它可以很好:https://play.golang.org/p/j5bDaj3z7y
实际上,来自规格说明
一个“中断”语句在同一个函数中终止最内部的"for“、"switch”或"select“语句的执行。
您可以使用return (就像我所做的那样)、goto或其他架构重构来解决这个问题。
至于无限循环,这是相同的问题,相反,关闭的通道总是返回,所以当break退出select时,输入回循环,并永远从关闭的通道接收nil。
https://stackoverflow.com/questions/37156960
复制相似问题