关于 golang channel 的问题,希望懂的大佬能进来看看

2019-08-28 15:00:06 +08:00
 zyt19940914

关于 channel 在 golang 中国的官网上写着这样一句话:

使用信道需要考虑的一个重点是死锁。当 Go 协程给一个信道发送数据时,照理说会有其他 Go 协程来接收数据。如果没有的话,程序就会在运行时触发 panic,形成死锁。

同理,当有 Go 协程等着从一个信道接收数据时,我们期望其他的 Go 协程会向该信道写入数据,要不然程序就会触发 panic。

问题一: 如果是无缓冲的 channel,协程给一个信道发数据 但是没有其他协程接收数据,个人实测下来并没有出现死锁....

问题二: 无缓冲的 channel 与有缓冲的 channel 发生死锁的场景区别,哪位能介绍下....?

3855 次点击
所在节点    Go 编程语言
24 条回复
liulaomo
2019-08-28 20:47:46 +08:00
@zyt19940914

> 使用信道需要考虑的一个重点是死锁。当 Go 协程给一个信道发送数据时,照理说会有其他 Go 协程来接收数据。如果没有的话,程序就会在运行时触发 panic,形成死锁。
> 同理,当有 Go 协程等着从一个信道接收数据时,我们期望其他的 Go 协程会向该信道写入数据,要不然程序就会触发 panic。

这个需要需要上下文情景理解。 不过无论如何,这么描述都是欠妥的。这两句话想强调的是当所有用户协程都同时阻塞时,程序将崩溃退出(非 panic )。但这只是官方编译器的实现,白皮书对此并未做要求。

@1608637229
取子切片时,第二个下标可以大于基础切片的长度,但是不能大于基础切片的容量。具体见 @lilydjwg 列出的白皮书中的一段。
janxin
2019-08-29 08:08:09 +08:00
Go 的 runtime 是在调度过程中发现所有 goroutine 都处于等待状态时就才会发出 all goroutines are asleep - deadlock panic 的。这里比较容易迷惑人的是:不是出现了 panic 才有死锁,在实际应用中不出现 panic 的时候也有可能有死锁。
janxin
2019-08-29 08:21:42 +08:00
@lilydjwg 这个是调度器检查的,当所有 goroutine 都阻塞住了才 panic。
poplar50
2019-08-29 09:35:55 +08:00
重点不是缓不缓冲,死锁是资源占用逻辑问题,如果一个协程需要从 channel 接收数据,主程发现除了该协程其他协程已经执行完毕了,那么就那个协程就永远接收不到数据,一直 block。
同理 一个协程需要发送数据,但 channel 已满,这是它是 block 的状态,然后如果其他协程都已经执行完毕了,channel 仍然是慢的,此时这个协程如果不控制也会一直 block 下去,这个时候,也应该报死锁。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/595892

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX