1 回答
TA贡献1794条经验 获得超8个赞
当主goroutine 返回时,整个运行时系统退出,相当突然。因此,任何卡在无缓冲或完整通道上等待发送的 goroutines 都将……不复存在。它们不会取消,不会运行,也不会等待。 把它想象成闪光纸着火了。
可以将此称为 goroutine 泄漏,就像在程序终止“泄漏”之前可以引用任何未关闭或释放的资源(例如打开的文件)一样。但是由于整个过程终止,所以什么都没有了。这里没有真正的泄漏。这不是一个整洁的清理,但系统确实清理了。
作为示例,这是一个游乐场链接。
(如果你使用 Go 系统本身没有定义的东西,你可能会以这种方式出现各种泄漏。例如,在旧的 System V 共享内存世界中,你可以创建共享内存段(shm_open)并且如果你从不关闭和取消链接他们,他们坚持。这是设计使然:他们的行为很像文件系统中的文件,只是它们存在于内存中,而不是存在于某种磁盘驱动器或其他任何东西上。但这远远超出了日常生活的正常范围去编程。)
重新编辑:如果主goroutine没有退出,所以程序仍在运行,其他 goroutines 继续运行(或等待)直到他们用完所有事情并返回自己,或者做一些导致他们退出的事情(比如打电话runtime.Goexit,或者做一些引起恐慌的事情)。在这种情况下,就是:等待响应,然后将响应发送到通道中,然后返回。假设他们得到响应,他们会将响应放入通道中。假设将响应放入通道有效(不恐慌也不阻塞),然后它们将返回。回来后,他们完成了,他们蒸发了。通道本身持续存在并持有字符串:这是资源泄漏,尽管是次要的,尤其是在玩具程序中。
如果没有对通道本身的引用,则通道本身以及其中的字符串将被垃圾回收;这清理了泄漏的资源。由于我们假设它mirroredQuery已经返回,并且此时最后一个分离出来的 goroutine 也已经返回,这是对通道的最后引用,所以现在可以对通道进行 GC。(这种情况是否发生以及何时发生取决于运行时。)在这些 goroutine 中的最后一个完成之前,仍然至少有一个对通道的引用,从而阻止通道(以及字符串)被 GC。
如果通道是无缓冲的,那么两个“丢失”的 goroutine 将阻止发送到通道的尝试。这将导致那些 goroutines 保留下来,这反过来又会导致通道保留下来,这又会导致资源保持分配状态,直到程序作为一个整体终止。所以那将是“坏的”。
关闭通道后,两个“失败”的 goroutine 可能会尝试在关闭的通道上发送mirroredQuery ,这将导致它们调用恐慌代码,从而终止程序。那也将是“坏的”。实现预期结果的最简单代码是使通道缓冲。
如果其中一个 goroutine 等待(响应)数年,那么这些年将保留那些“泄漏”的资源。这也将是“坏的”(轻微),所以我们想确保他们不会永远等待。但这在小型演示程序中是不切实际的。
- 1 回答
- 0 关注
- 129 浏览
添加回答
举报