首先说下死锁发生的场景:从‘干涸’的channel读取数据会发生死锁
干涸有两种场景(可能有遗漏,欢迎补充):
1.channel被初始化,但未投入数据
2.有缓冲的channel中已投入数据,并且被读取完毕后(未及时关闭channel)仍从chanel读取数据时
package main
import "fmt"
var ch1 = make(chan int)
var ch2 =make(chan int,2)
func main(){
go sayHello()
ch1 <- <-ch2
ch2<- 1
}
func sayHello(){
fmt.Println("hello",<-ch1)
}
之前没有好好理解过channel的死锁这个概念,直到遇见了这个笔试题,问有什么问题,当时想的有两种可能,panic和阻塞,然而敲了下代码发现,发生了死锁。。。泪奔
ch1 <- <-ch2
ch2<- 1
为什么会发生死锁,简而言之就是ch1和ch2都在等待读数据,但都等不到
首先,ch1为无缓冲通道,ch2有缓冲,ch1必须在发送方和接收放都在场时才不会阻塞,对ch1而言,接收方已经就绪,发送方是<-ch2,如果ch2内有数据 ,ch1就不会阻塞了,但在执行ch1 <- <-ch2时,ch2本身是干涸的,读取干涸的channel会发生死锁
package main
import "fmt"
func main() {
ch := make(chan int, 3)
// 在无数据填入ch时,执行fmt.Println(<-ch),会发生死锁
// fmt.Println(<-ch)
ch <- 1
ch <- 2
ch <- 3
for v := range ch {
fmt.Println(v)
//在读取完ch时,若不关闭ch,继续读取,也同样会发生死锁
// if v==3{
// close(ch)
// }
}
}