老师,您好!channel死锁的问题
来源:13-9 使用channel容易出现deadlock的原因

慕斯0066757
2022-06-24
截图中的代码:
forever:是一个无缓冲的通道
<- forever:没有任何goroutine向forever管道生产数据,一直阻塞中
或者
forever <- true:没有任何goroutine从forever管道读取数据,一直阻塞中
执行后,会一直循环打印555,并未出现deadlock死锁现象
学生的困惑如下:
正因为上述代码能正确执行,并没有出现deadlock死锁现象,反而让学生陷入了困惑
因为在学习channel这一章节时,学生私下总结了一条结论:goroutine的生产与消费都需要准备就绪,理解的白话文就是channel像是一个流水的管道,读取与写入都需要准备好,否则容易产生deadlock死锁现象,但上述代码却好像违背了这一结论,只有读或者只有写时,也没有出现deadlock死锁现象
请老师能指点一下,学生该如何正确理解channel呢?
2回答
-
慕妹3255656
2023-12-05
我也是想了很久才明白。
首先,老师说的没错,如果没有缓存的话,接受者如果没有准备就绪,,发送者就会被阻塞。但阻塞不一定是deadlock。
比如你在主线程里先往一个没有接受者的无缓冲channel里发送数据,那一定是死锁。因为没有缓存,那主线程执行到这里就被阻塞了,连启动接收者goroutine的机会都没有,就是死锁。但你只要不在主线程里这样写,写在子线程里,接收者和发送者谁先执行都完全没有关系,发送者一定是等到接收者启动才能往channel里写数据,因为是不在主线程,接收者和发送者的goroutine都被启动,所以不存在死锁。
缓存的作用是让发送者在向channel里发送数据时,直到buffer满之前不被阻塞。所以如果有缓存的channel,你在主线程里先往channel发送数据也是没问题的,因为不会被阻塞,底下的负责接受的线程或代码能有机会被执行。
至于有没有报错问题,deadlock是一个runtime错误,也就是执行之后才知道。这个可能和go版本有关,这段程序从理论上说就是死锁,因为forever <- true以后的代码没有机会执行。如果那个子协程不是无限循环的话,也会报runtime错误。
012023-12-07 -
bobby
2022-06-25
刚才我也试了一下发现也没有这个问题, 你的go的版本是多少,有可能新版本对这个问题进行了修改
022022-06-28
相似问题