1 回答

TA貢獻(xiàn)1794條經(jīng)驗(yàn) 獲得超8個(gè)贊
當(dāng)主goroutine 返回時(shí),整個(gè)運(yùn)行時(shí)系統(tǒng)退出,相當(dāng)突然。因此,任何卡在無(wú)緩沖或完整通道上等待發(fā)送的 goroutines 都將……不復(fù)存在。它們不會(huì)取消,不會(huì)運(yùn)行,也不會(huì)等待。 把它想象成閃光紙著火了。
可以將此稱(chēng)為 goroutine 泄漏,就像在程序終止“泄漏”之前可以引用任何未關(guān)閉或釋放的資源(例如打開(kāi)的文件)一樣。但是由于整個(gè)過(guò)程終止,所以什么都沒(méi)有了。這里沒(méi)有真正的泄漏。這不是一個(gè)整潔的清理,但系統(tǒng)確實(shí)清理了。
作為示例,這是一個(gè)游樂(lè)場(chǎng)鏈接。
(如果你使用 Go 系統(tǒng)本身沒(méi)有定義的東西,你可能會(huì)以這種方式出現(xiàn)各種泄漏。例如,在舊的 System V 共享內(nèi)存世界中,你可以創(chuàng)建共享內(nèi)存段(shm_open)并且如果你從不關(guān)閉和取消鏈接他們,他們堅(jiān)持。這是設(shè)計(jì)使然:他們的行為很像文件系統(tǒng)中的文件,只是它們存在于內(nèi)存中,而不是存在于某種磁盤(pán)驅(qū)動(dòng)器或其他任何東西上。但這遠(yuǎn)遠(yuǎn)超出了日常生活的正常范圍去編程。)
重新編輯:如果主goroutine沒(méi)有退出,所以程序仍在運(yùn)行,其他 goroutines 繼續(xù)運(yùn)行(或等待)直到他們用完所有事情并返回自己,或者做一些導(dǎo)致他們退出的事情(比如打電話(huà)runtime.Goexit,或者做一些引起恐慌的事情)。在這種情況下,就是:等待響應(yīng),然后將響應(yīng)發(fā)送到通道中,然后返回。假設(shè)他們得到響應(yīng),他們會(huì)將響應(yīng)放入通道中。假設(shè)將響應(yīng)放入通道有效(不恐慌也不阻塞),然后它們將返回?;貋?lái)后,他們完成了,他們蒸發(fā)了。通道本身持續(xù)存在并持有字符串:這是資源泄漏,盡管是次要的,尤其是在玩具程序中。
如果沒(méi)有對(duì)通道本身的引用,則通道本身以及其中的字符串將被垃圾回收;這清理了泄漏的資源。由于我們假設(shè)它mirroredQuery已經(jīng)返回,并且此時(shí)最后一個(gè)分離出來(lái)的 goroutine 也已經(jīng)返回,這是對(duì)通道的最后引用,所以現(xiàn)在可以對(duì)通道進(jìn)行 GC。(這種情況是否發(fā)生以及何時(shí)發(fā)生取決于運(yùn)行時(shí)。)在這些 goroutine 中的最后一個(gè)完成之前,仍然至少有一個(gè)對(duì)通道的引用,從而阻止通道(以及字符串)被 GC。
如果通道是無(wú)緩沖的,那么兩個(gè)“丟失”的 goroutine 將阻止發(fā)送到通道的嘗試。這將導(dǎo)致那些 goroutines 保留下來(lái),這反過(guò)來(lái)又會(huì)導(dǎo)致通道保留下來(lái),這又會(huì)導(dǎo)致資源保持分配狀態(tài),直到程序作為一個(gè)整體終止。所以那將是“壞的”。
關(guān)閉通道后,兩個(gè)“失敗”的 goroutine 可能會(huì)嘗試在關(guān)閉的通道上發(fā)送mirroredQuery ,這將導(dǎo)致它們調(diào)用恐慌代碼,從而終止程序。那也將是“壞的”。實(shí)現(xiàn)預(yù)期結(jié)果的最簡(jiǎn)單代碼是使通道緩沖。
如果其中一個(gè) goroutine 等待(響應(yīng))數(shù)年,那么這些年將保留那些“泄漏”的資源。這也將是“壞的”(輕微),所以我們想確保他們不會(huì)永遠(yuǎn)等待。但這在小型演示程序中是不切實(shí)際的。
- 1 回答
- 0 關(guān)注
- 161 瀏覽
添加回答
舉報(bào)