1 回答
TA贡献1775条经验 获得超11个赞
事实是,没有缓冲区的通道称为同步通道,它将阻塞发送方和接收方,直到他们完成交换。
就像如果你不得不把东西交给你的伴侣,你们都知道会面的地点,但不知道时间。第一个到达那里将等待另一个,无论是发送者还是接收者。现在,考虑到计算机是愚蠢的 :-) 如果其中一个忘记了约会,另一个将永远等待。
The specific bug here is that when the select chooses the time.After
(that is, the timeout occurs) nobody will be there to receive from <-ch
anymore. 永远不会。所以穷人go func()
会永远坐在那里,等待有人带走她*Response
,但永远不会有人出现。
这实际上并没有浪费任何 CPU 能力,而是浪费了内存:需要跟踪通道、goroutine、她的堆栈(无论多小)和她的局部变量。在整个进程终止或被杀死之前,永远不会回收内存。
在为大量客户端提供服务的服务器中,这种情况会迅速增加,直到应用程序吃掉服务器的所有内存,并且——如果你幸运的话——被操作系统安全措施杀死,而不会关闭整个机器。
使用缓冲通道,是解决问题的一种方式,因为那样的话,只要穷人go func()
有她*Response
准备好了,她就可以将其存储到通道的缓冲区,即使没有人在那里得到它,而和平结束。一旦发生这种情况,Go 的垃圾收集器会注意到没有活动的 goroutine 再持有任何指向该通道的指针,因此它将收集该通道及其*Response
指向并回收所有这些字节。
- 1 回答
- 0 关注
- 164 浏览
添加回答
举报