无缓冲通道是否等待数据?

Tro*_*yvs -1 buffer locking channel go

我有这个程序:

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")
}
Run Code Online (Sandbox Code Playgroud)

我想到的是,只要F1和F2不显示任何信息,这意味着CH1和CH2具有里面什么都没有,所以ch1<-1ch2<-2应该阻止?

但是当运行时,它会打印:

no buffered channel will wait?
main exits
Run Code Online (Sandbox Code Playgroud)

为什么那些无缓冲通道ch1,并ch2没有阻止内主?

如果我不调用f1/ f2in main,它会dead lock报错。

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

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

icz*_*cza 7

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

所以你启动f1()f2()作为新的 goroutines,然后main()睡觉。同时f1()f2()正在等待来自ch1和 的数据ch2

然后main()醒来,并尝试在 上发送一个值ch1。这是可以的,因为有一个 goroutine 准备好从它 ( f1())接收。然后main()尝试发送ch2,这也行,有f2()准备从它接收。

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

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