【问题标题】:does unbuffered channel wait for data?无缓冲通道是否等待数据?
【发布时间】:2020-04-09 23:14:48
【问题描述】:

我有这个程序:

package main

import (
    "fmt"
    "time"
)

var ch1 = make(chan int)
var ch2 = make(chan int)

func f1() {
    select {
    case <-ch1:
        fmt.Println("ch1")
    }
}
func f2() {
    select {
    case <-ch2:
        fmt.Println("ch2")
    }
}
func main() {
    go f1()
    go f2()
    time.Sleep(2 * time.Second)
    fmt.Println("no buffered channel will wait?")
    ch1 <- 1
    ch2 <- 2
    fmt.Println("main exits")
}

我希望,只要 f1 和 f2 不打印任何东西,就意味着 ch1 和 ch2 里面什么都没有,所以 ch1&lt;-1ch2&lt;-2 应该阻塞?

但运行时,它会打印:

no buffered channel will wait?
main exits

为什么那些无缓冲的频道 ch1ch2 在 main 中没有被阻塞?

如果我在main中不调用f1/f2,就会报dead lock错误。

我不明白 f1/f2 对 ch1/ch2 做了什么。

您能帮忙解释一下他们的行为吗?

【问题讨论】:

  • 通常的约定是谈论bufferedunbuffered 频道。其中buffered 频道有一个buffer length &gt; 1,它允许push 无需等待pop 操作。另一方面,由于unbuffered 通道有一个空缓冲区,每个push 操作都需要来自另一个例程的pop

标签: go locking buffer channel


【解决方案1】:

f1()f2() 都有接收操作。这些是阻塞操作:只要通道上没有人发送任何东西,他们就等待

所以你启动 f1()f2() 作为新的 goroutine,然后 main() 休眠。同时f1()f2() 正在等待来自ch1ch2 的数据。

然后main() 被唤醒,并尝试在ch1 上发送一个值。这没关系,因为有一个 goroutine 准备好接收它(f1())。然后main() 尝试在ch2 上发送,这也可以,有f2() 准备接收。

然后main() 返回,应用程序结束(它不等待其他 goroutine 打印)。

如果你不启动 f1()f2() 作为新的 goroutines,当 main() 到达发送语句时,将没有人准备好从通道接收,并且由于它没有缓冲,它会阻塞。而且由于不会有更多的 goroutine 运行,这是一个死锁。

【讨论】:

    猜你喜欢
    • 2016-12-12
    • 2023-02-11
    • 1970-01-01
    • 2016-06-20
    • 1970-01-01
    • 2014-11-05
    • 2021-10-29
    • 2014-01-30
    • 1970-01-01
    相关资源
    最近更新 更多