Go 为什么我的围棋程序出现死锁?
我对golang编程非常陌生,我有以下产生死锁的程序,我不明白为什么 另一件事是,如果我在Go 为什么我的围棋程序出现死锁?,go,Go,我对golang编程非常陌生,我有以下产生死锁的程序,我不明白为什么 另一件事是,如果我在doAdd方法中关闭通道,那么我将进入一个无限循环,这对我来说也有点奇怪 这是节目单 var wg sync.WaitGroup func main() { ch1 := make(chan string) ch2 := make(chan string) ch3 := make(chan string) chClose := make(chan bool) wg
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()
}
程序末尾的
中断
只会中断选择
(并再次进入循环,因此出现死锁):将其替换为返回
效果良好:
事实上,从以下方面:
“break”语句终止同一函数中最内层的“for”、“switch”或“select”语句的执行
您可以通过返回(就像我做的那样)、goto或其他一些架构重构来解决这个问题
至于无限循环,这是同样的问题,相反,封闭通道总是返回,因此当中断退出选择时,您返回循环,并从封闭通道接收零
s,直到永久您的中断
在程序结束时仅中断选择(并再次进入循环,因此出现死锁):将其替换为return
可以正常工作:
事实上,从以下方面:
“break”语句终止同一函数中最内层的“for”、“switch”或“select”语句的执行
您可以通过返回(就像我做的那样)、goto或其他一些架构重构来解决这个问题
至于无限循环,这是同样的问题,相反,封闭通道总是返回,因此当中断退出选择时,您返回循环,并从封闭通道永远接收零死锁的原因是中断在选择中y从select
中断,让for
循环自由地重新进入select,此时没有任何通道准备好读取
您可以通过执行以下操作来拯救此问题:
done := false
for !done {
select {
...
case <-chClose:
done = true
fmt.Println("CLOSED")
}
}
一、 就个人而言,在这种情况下,对第一个版本有一点偏好,但这只是口味的问题。出现死锁的原因是select
中的break
只会从select
中中断,让for
循环自由地重新进入select,其中没有任何频道我们已经准备好阅读
您可以通过执行以下操作来拯救此问题:
done := false
for !done {
select {
...
case <-chClose:
done = true
fmt.Println("CLOSED")
}
}
一、 就个人而言,在这种情况下,对第一个版本有一点偏好,但这仅仅是口味的问题。也有标签的break也有标签的break
OuterLoop:
for {
select {
...
case <-chClose:
fmt.Println("CLOSED")
break OuterLoop
}
}