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

单个通道上的多个接收器。谁得到数据?

单个通道上的多个接收器。谁得到数据?

Go
慕森卡 2021-10-25 16:10:02
无缓冲通道阻塞接收器,直到通道上有数据可用。我不清楚这种阻塞是如何与同一通道上的多个接收器一起工作的(比如在使用 goroutines 时)。我敢肯定,只要该通道上没有发送数据,它们都会阻塞。但是,一旦我向该通道发送单个值会发生什么?哪个接收器/goroutine 将获取数据并因此解除阻塞?他们都?第一个?随机的?
查看完整描述

3 回答

?
慕妹3146593

TA贡献1820条经验 获得超9个赞

一个随机(非确定性)的人会收到它。

请参阅语言规范

“select”语句的执行分几个步骤:

  1. 对于语句中的所有情况,接收操作的通道操作数以及发送语句的通道和右侧表达式在进入“选择”语句时按源顺序被计算一次。结果是一组要接收或发送的通道,以及要发送的相应值。无论选择哪个(如果有)通信操作进行,该评估中的任何副作用都会发生。带有简短变量声明或赋值的 RecvStmt 左侧的表达式尚未计算。

  2. 如果可以进行一个或多个通信,则通过统一伪随机选择选择可以进行的单个通信。 否则,如果存在默认情况,则选择该情况。如果没有默认情况,“select”语句会阻塞,直到至少有一个通信可以继续。

  3. 除非选择的情况是默认情况,否则将执行相应的通信操作。

  4. 如果选定的 case 是带有短变量声明或赋值的 RecvStmt,则评估左侧表达式并分配接收到的值(或多个值)。

  5. 执行所选案例的语句列表。


查看完整回答
反对 回复 2021-10-25
?
慕桂英546537

TA贡献1848条经验 获得超10个赞

默认情况下,goroutine 通信是synchronousand unbuffered: 发送不会完成,直到有接收者接受该值。必须有一个接收者准备好从通道接收数据,然后发送者可以将它直接交给接收者。


所以通道发送/接收操作阻塞,直到另一端准备好:


1.通道上的发送操作会阻塞,直到接收器可用于同一通道:如果没有接收器的值 on ch,则不能将其他值放入通道。反之亦然:ch当通道不为空时,不能发送新值!因此发送操作将等待直到ch再次可用。


2.通道的接收操作阻塞,直到发送方可用于同一通道:如果通道中没有值,则接收方阻塞。


下面的例子说明了这一点:


package main

import "fmt"


func main() {

    ch1 := make(chan int)

    go pump(ch1) // pump hangs

    fmt.Println(<-ch1) // prints only 0

}


func pump(ch chan int) {

    for i:= 0; ; i++ {

        ch <- i

    }

}

因为没有接收器,goroutine 挂起并只打印第一个数字。


为了解决这个问题,我们需要定义一个新的 goroutine,它以无限循环的方式从通道中读取数据。


func receive(ch chan int) {

    for {

        fmt.Println(<- ch)

    }

}

然后在main():


func main() {

    ch := make(chan int)

    go pump(ch)

    receive(ch)

}


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

添加回答

举报

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