2014-01-11 165 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