在看go入门指南时遇到一个问题,下面的程序为什么会产生死锁。
package main
import (
"fmt"
)
func f1(in chan int) {
fmt.Println(<-in)
}
func main() {
out := make(chan int)
out <- 2
go f1(out)
}
书中说到:
通道的发送/接收操作在对方准备好之前是阻塞的:
,按理说,out <- 2
等到fmt.Println(<-in)
准备好就可以执行了,不应该产生死锁啊,求解
但是,当我调整了一下顺序,就可以了
func f1(in chan int) {
fmt.Println(<-in)
}
func main() {
out := make(chan int)
go f1(out)
out <- 2
}
// 结果:
2
然后在调整一点
func f1(in chan int) {
in <- 2
fmt.Println("in")
}
func main() {
out := make(chan int)
<-out
go f1(out)
}
// 结果依然是死锁
如果此时和上面一样调整一下顺序
func f1(in chan int) {
in <- 2
fmt.Println("in")
}
func main() {
out := make(chan int)
go f1(out)
<-out
}
// 结果为 in
我又尝试了一下
func f1(in chan int) {
in <- 2
fmt.Println("in")
}
func main() {
out := make(chan int)
<-out
fmt.Println("out")
go f1(out)
}
此时的结果是死锁,还有一个关键的点是:没有打印出
out
我猜:是不是由于在执行<-out
时阻塞,而此时只有一个协程,并没有执行go f1(out)
,所以导致channel的双方并没有准备好,进而产生了死锁。不知道对不对,好纠结???
https://segmentfault.com/q/10...
完全一样的问题……
有啥好纠结的……
记住一点,单纯的out<-和<-in都会阻塞,只有两个同时进行了,才能继续执行。
这里你看上去有个协程,来执行<-in,但是实际上已经阻塞在out<-2了,协程没办法执行下去……
解决办法就两个,要么在out <- 2之前开一个协程去消费这个channel,
要么就给这个channel加个大小,让他里面默认能存1个数据,这样才不会阻塞,即:
make(chan int, 1)