写入通道的随机结果(Go)

问题描述 投票:0回答:1

我有以下代码:

func writeToClosedBufferedChannel() {
    ch := make(chan int, 2)
    ch <- 10
    ch <- 20

    go func() {
        fmt.Println("test")
        ch <- 30
    }()

    time.Sleep(100 * time.Millisecond)
    fmt.Println("before")
    close(ch)

    fmt.Println("after")
    for value := range ch {
        fmt.Println(value)
    }
}

我的这段代码有不同的结果:

test
before
after
panic: send on closed channel

test
before
after
10
20

test
before
after
10
20
panic: send on closed channel

我知道,关闭后我无法写入频道,但为什么它会随机工作?我想检查一下,从 sendq 写入关闭通道后会发生什么,但现在我无法理解......

go concurrency scheduler channel
1个回答
0
投票

通道容量为2,因此10和20将被写入通道。 goroutine 将打印“test”,然后因为通道已满而阻塞。为了让它写入 30,另一个 goroutine 必须首先从通道读取。所以在测试之后,“before”和“after”也被打印出来,此时,你有一个关闭的通道,并且goroutine仍在等待写入通道。然后你开始从频道中阅读,可能会发生多种事情:

在您显示的第一个输出中,从通道中读取的第一个数据会解锁 goroutine,该 goroutine 由运行时调度并发送到关闭的通道,从而导致恐慌。

在第二个输出中,goroutine 被解除阻塞,但没有立即调度,因此主 goroutine 从通道读取两个值,程序终止。

在第三个输出中,goroutine 被解除阻塞,但仅在打印两个值之后、程序终止之前进行调度。

© www.soinside.com 2019 - 2024. All rights reserved.