缓冲/无缓冲通道

时间:2014-01-11 20:52:50

标签: go

有人可以解释,为什么如果频道被缓冲,程序不会以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.

谢谢!

3 个答案:

答案 0 :(得分:11)

如果缓冲区中有空间,则写入缓冲通道不会阻止。

如果您尝试在缓冲区大小为1的通道中放入两个项目,则会出现相同的错误:

package main

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

给你:

fatal error: all goroutines are asleep - deadlock!

答案 1 :(得分:3)

这是Go的频道(或其他CSP实现,如Clojure的core.async库)的核心概念,它们正在阻止它们。一般来说,正如您已经提到的,有两种类型的渠道:

  • 缓冲,如果缓冲区已满,则会阻止。
  • unbuffered ,如果没有“会合”,则会阻止,即必须有人向该频道投放(c <-)和从中获取(<- c)的人。

在您的特定情况下,Go运行时足够聪明,可以检测到没有人会从频道3中获取c。因此,它是deadlock并且(幸运的是)抛出了一个错误。

当您使用频道时,您通常使用 goroutines (checkout this introduction)来生成由Go运行时管理的轻量级线程,以同时执行主体:

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

答案 2 :(得分:2)

谢谢@Matt

我在这篇文章中找到了答案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.