Go语言学习——channel的死锁其实没那么复杂 - JackieZheng - 博客园 (cnblogs.com)
目录
通道
创建通道
1)无缓冲通道
2)有缓冲通道
通道的使用
1) 值从通道入口进
2) 值从通道出口出
信道死锁:
0)死锁现场0
1)死锁现场1
1.5)总结通道死锁的两个规律。
2)死锁现场2
3)死锁现场3
实际运行情况如下:
解决方案
4)死锁现场4
通道
创建通道
1)无缓冲通道
channels := make( chan string)
make关键字用来创建切片 字典 通道;在这里make创建了通道类型,通道能传输的值是string类型
无缓冲通道不保存值,只负责即时性的传输。当调用通道只有入口或者只有出口时,发生死锁。
2)有缓冲通道
channels := make(chan string,2)
有缓冲通道可以暂时存储值,channels对象可以存储2个字符串类型的变量。
通道的使用
channels := make( chan string)
1) 值从通道入口进
channels <- "ping"
2) 值从通道出口出
msg := <- channels
信道死锁:
0)死锁现场0
main()单协程中匿名函数中调用通道入口,func()并没有加go关键字变成协程。
main()会运行到 channels <- int(i)这一步,然后期待main()函数的主协程去接收channels传过来的i值。
然而main()主协程也就是它本身,自身等待自身,意思是要它在吃饭的同时还要它喝水。
其实把匿名方法 func(){ }外壳去掉也一样 ,因为和匿名方法无关嘛,通道的死锁只和协程之间有关。
1)死锁现场1
和死锁现场0一样。
main函数单协程中只有通道的入口或者出口其一。
1.5)总结通道死锁的两个规律。
通道是在协程之间传输数据的。通道只存在单协程中调用肯定发生死锁,
因为他不能在从入口传输的过程中 又去出口接收值。这项工作至少要两个协程完成。
只有通道的入口或者出口也会死锁。只有入口协程会等一个出口放值;只有出口协程会等待入口传值。
2)死锁现场2
ch2 只有入口,没有出口 。go func()线程在ch2的入口出就发生死锁。
3)死锁现场3
main()主协程执行顺序是
1) 接收 ch1 出口值 , 等待ch1入口传值完成。
2)在完成主协程步骤1)后 ,
再接收 ch2 出口值。
go func()副协程执行顺序
1)从 ch2入口 传输 一个值,等待ch2出口传值完成。
2)在完成副协程步骤1)后,
从 ch1 入口 传输 一个值。
两个协程间是并行运行的,每个协程都是一个独立执行的单元,这是协程的特点。
mian()协程运行到 <- ch1肯定在等待一个ch1的入口传值
go func协程运行到 ch2 <- "ch2 value" 也在等一个ch2的出口传值。
实际运行情况如下:
解决方案
mian()协程运行到 <- ch2肯定在等待一个ch2的入口传值
go func协程运行到 ch2 <- "ch2 value" 也在等一个ch2的出口传值。
这个时候就是标准的双向奔赴了。
4)死锁现场4
输出完前两个值后,变成无缓冲通道,这个时候再去获取值和死锁现场0,1一样。