猿问

go 通道在阻塞时会保持顺序吗?

我有一部分频道都收到相同的消息:


func broadcast(c <-chan string, chans []chan<- string) {

    for msg := range c {

        for _, ch := range chans {

            ch <- msg

        }

    }

}

但是,由于每个通道chans都可能以不同的速率被读取,因此当我遇到慢消费者时,我不想阻止其他通道。我已经用 goroutines 解决了这个问题:


func broadcast(c <-chan string, chans []chan<- string) {

    for msg := range c {

        for _, ch := range chans {

            go func() { ch <- msg }()

        }

    }

}

但是,传递到每个通道的消息的顺序很重要。我查看了规范以查看通道在阻塞时是否保持顺序,我发现的是:


如果容量大于零,则通道是异步的:如果缓冲区未满(发送)或非空(接收),则通信操作成功而不会阻塞,并且元素按发送顺序接收。


对我来说,如果写入被阻塞,那么它不是“发送”,而是等待发送。有了这个假设,当多个 goroutines 在写入时被阻塞时,上面没有说明发送的顺序。


通道解除阻塞后,是否有任何关于发送顺序的保证?


狐的传说
浏览 293回答 3
3回答

肥皂起泡泡

在此代码中,没有任何保证。给定示例代码的主要问题不在于通道行为,而在于创建的众多 goroutine。所有的 goroutine 都在同一个叠片循环中“触发”而无需进一步同步,因此即使在它们开始发送消息之前,我们也不知道哪些将首先执行。然而,这通常会引发一个合理的问题:如果我们以某种方式保证几个阻塞发送指令的顺序,我们是否保证以相同的顺序接收它们?发送的“发生在之前”属性很难创建。我担心这是不可能的,因为:在发送指令之前任何事情都可能发生:例如,其他 goroutine 是否执行自己的发送在发送中被阻塞的 goroutine 不能同时管理其他类型的同步例如,如果我有 10 个编号为 1 到 10 的 goroutine,我无法让它们以正确的顺序同时将自己的编号发送到通道。我所能做的就是使用各种顺序技巧,例如在 1 个单独的 goroutine 中进行排序。

aluckdog

不,没有任何保证。即使通道未满,如果两个 goroutine 大约在同一时间启动并发送给它,我认为无法保证首先启动的 goroutine 会真正先执行。所以你不能指望消息按顺序到达。
随时随地看视频慕课网APP

相关分类

Go
我要回答