为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
狐的传说 2021-06-04 16:53:01
我有一部分频道都收到相同的消息: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 在写入时被阻塞时,上面没有说明发送的顺序。通道解除阻塞后,是否有任何关于发送顺序的保证?
查看完整描述

3 回答

?
肥皂起泡泡

TA贡献1829条经验 获得超6个赞

在此代码中,没有任何保证。

给定示例代码的主要问题不在于通道行为,而在于创建的众多 goroutine。所有的 goroutine 都在同一个叠片循环中“触发”而无需进一步同步,因此即使在它们开始发送消息之前,我们也不知道哪些将首先执行。

然而,这通常会引发一个合理的问题:如果我们以某种方式保证几个阻塞发送指令的顺序,我们是否保证以相同的顺序接收它们?

发送的“发生在之前”属性很难创建。我担心这是不可能的,因为:

  1. 在发送指令之前任何事情都可能发生:例如,其他 goroutine 是否执行自己的发送

  2. 在发送中被阻塞的 goroutine 不能同时管理其他类型的同步

例如,如果我有 10 个编号为 1 到 10 的 goroutine,我无法让它们以正确的顺序同时将自己的编号发送到通道。我所能做的就是使用各种顺序技巧,例如在 1 个单独的 goroutine 中进行排序。


查看完整回答
反对 回复 2021-06-07
?
aluckdog

TA贡献1847条经验 获得超7个赞

不,没有任何保证。

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


查看完整回答
反对 回复 2021-06-07
  • 3 回答
  • 0 关注
  • 292 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信