2016-06-29 74 views
5

想象一下下面的代碼:goroutines垃圾是否與他們的渠道一起收集?

func waitForOneOfTwoProcesses() { 

    c := make(chan bool) 
    go func() { 
     time.Sleep(1 * time.Second) 
     c<-true 
    }() 
    go func() { 
     time.Sleep(2 * time.Second) 
     c<-true 
    }() 
    <-c 

} 

這是否泄漏通道和一個夠程或不會去承認c消失,且夠程可以退出?

如果通道的緩衝區大小爲2,答案會不同嗎?

回答

3

如果通道未經緩衝,則其中一個匿名函數將不會返回。該程序泄漏了一個goroutine和頻道。

如果通道的緩衝區大小大於或等於1,則兩個匿名函數都會返回。 goroutines和渠道使用的資源將被回收。

一個緩衝區的大小足以防止泄漏。功能waitForOneOfTwoProcesses收到發送到c的值之一。發送到c的第二個值被緩存在通道中(由GC收集)。

確保goroutines返回的另一種方法是使用非阻塞發送。將c <- true行替換爲:

select { 
case c <- true: 
default: 
} 
+0

因此,即使通道超出範圍且永遠不能再次讀取,通道塊的寫入也會被阻止。我不知道這是一個錯誤還是一個功能。 – AndreKR

+0

是的,即使沒有接收器,發送也會阻止。可以編寫運行時來檢測應用程序何時完成在此特定示例中的頻道接收,但它不是運行時通常可檢測到的內容。 –

+1

需要注意的是,還有一個「非阻塞發送」功能可以解決這個問題 - 您可以將通道上的緩衝區設置爲1,並且每個通道都可以無阻塞地發送。在這裏更詳細地描述:https://blog.golang.org/go-concurrency-patterns-timing-out-and –