【问题标题】:buffered channel not blocking for write when reached its capacity缓冲通道在达到其容量时不会阻塞写入
【发布时间】:2021-12-11 07:42:57
【问题描述】:

https://play.golang.org/p/5A-dnZVy2aA

func closeChannel(stream chan int) {
    fmt.Println("closing the channel")
    close(stream)
}

func main() {
    chanOwner := func() <-chan int {
        resultStream := make(chan int, 5)
        go func() {
            defer closeChannel(resultStream)
            for i := 0; i <= 5; i++ {
                resultStream <- i
            }
        }()
        return resultStream
    }
    resultStream := chanOwner()
    for result := range resultStream { //this blocks until the channel is closed
        fmt.Printf("Received: %d\n", result)
    }
    fmt.Println("done receiving")
}

程序的输出

closing the channel
Received: 0
Received: 1
Received: 2
Received: 3
Received: 4
Received: 5
done receiving

为什么在上面的程序中,closing the channel 语句打印在任何Received 之前。由于通道以 5 的容量缓冲,并且我们正在向其中插入 6 个元素,因此我希望它在读取值并清除缓冲区中的空间之前阻塞在 resultStream &lt;- i

【问题讨论】:

    标签: go concurrency


    【解决方案1】:

    生成器 goroutine 将通道填充到其容量并阻塞。循环的接收器从通道接收第一项,这再次启用生成器 goroutine。生成器 goroutine 在接收器 for 循环打印 Received 消息之前运行完成,打印 closing the channel 消息。然后接收者循环接收所有剩余的消息。

    【讨论】:

    • 不应该在“关闭通道”之前打印 Received,因为生成器在以最大容量运行时会阻塞?
    • 生成器 goroutine 可以在 for 循环读取第一条消息后立即运行,然后打印 Received 行。
    猜你喜欢
    • 2021-11-23
    • 2018-08-03
    • 2017-06-06
    • 2012-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-01
    • 1970-01-01
    相关资源
    最近更新 更多