2014-01-11 218 views
8

有人可以解釋一下,爲什麼如果通道被緩衝,程序不會以fatal_error退出?緩衝/無緩衝通道

無緩衝通道

package main 

func main() { 
    c := make(chan int) 
    c <- 3 
} 

fatal error: all goroutines are asleep - deadlock! 

緩衝通道

package main 

func main() { 
    c := make(chan int, 1) 
    c <- 3 
} 

[no output] 

Program exited. 

謝謝!

+0

我想這是因爲緩衝和非緩衝通道之間的差異。在緩衝的通道中,發送方等待接收方(本例中爲自己)獲取數據。但我不知道.. –

+2

可能的重複[如何使(chan布爾)行爲不同於make(chan bool,1)?](http://stackoverflow.com/questions/20041392/how-does-makechan -bool-表現-不同地從-makechan-布爾-1) – Matt

回答

11

如果緩衝區中有空間,寫入緩衝通道不會阻塞。

如果你試圖把兩個項目與一個緩衝區大小的通道,你得到同樣的錯誤:

package main 

func main() { 
    c := make(chan int, 1) 
    c <- 3 
    c <- 4 
} 

爲您提供:

fatal error: all goroutines are asleep - deadlock! 
1

感謝@馬特

我在這篇文章中找到了答案How does make(chan bool) behave differently from make(chan bool, 1)?

Actually that's the reason why your problem is generated. Un-buffered channels are only writable when there's someone blocking to read from it, which means you shall have some coroutines to work with -- instead of this single one.

2

這是Go的渠道(或其他CSP實現,如Clojure的core.async庫),他們阻止的核心概念。在一般情況下,因爲你已經提到的,這裏有兩種類型的通道:

  • 緩衝阻斷如果緩衝區已滿。
  • 無緩衝如果不存在「集合點」,即阻止(c <-)和某人(<- c)從頻道中阻止,哪個阻止。

在您的特定情況下,Go運行時足夠聰明,可以檢測到沒有人會從c頻道拿3。因此,這是一個deadlock和(幸好)一個錯誤被拋出。

當你與渠道合作使用夠程什麼你通常做的(檢出this introduction),它產生一個輕量級線程管理由圍棋身體運行時執行併發:

c := make(chan int) 

go func() { c <- 3 }() // Create a new gorountine that puts 3 to the channel 

fmt.Println(<- c) // Take 3 from the channel and print it in the main thread