【问题标题】:Buffered/Unbuffered channel缓冲/非缓冲通道
【发布时间】:2014-01-30 19:24:42
【问题描述】:

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

谢谢!

【问题讨论】:

标签: go


【解决方案1】:

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

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

package main

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

给你:

fatal error: all goroutines are asleep - deadlock!

【讨论】:

    【解决方案2】:

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

    • 缓冲如果缓冲区已满,则阻塞。
    • unbuffered 如果没有“集合点”,则阻塞,即必须有人将 (c &lt;-) 放入频道并从频道中取出 (&lt;- c)。

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

    当您使用通道时,您通常会使用 goroutines (checkout this introduction),它会产生一个由 Go 运行时管理的轻量级线程来同时执行主体: p>

    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
    

    【讨论】:

      【解决方案3】:

      谢谢@马特

      我在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.

      【讨论】:

        猜你喜欢
        • 2017-09-06
        • 2021-10-13
        • 2020-10-23
        • 2019-08-14
        • 2018-04-15
        • 2010-11-29
        • 2020-09-03
        • 2016-08-30
        相关资源
        最近更新 更多