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

时间:2015-07-21 13:02:50

标签: go blocking channel

无缓冲通道阻止接收器,直到通道上的数据可用。我不清楚这种阻塞在同一个通道上的多个接收器如何表现(比如使用goroutines时)。只要该频道上没有数据发送,我相信他们都会阻止 但是,一旦我向该频道发送单个值,会发生什么?哪个接收器/ goroutine将获取数据并因此解除阻塞?他们都是?排在第一位?随机?

3 个答案:

答案 0 :(得分:13)

单个随机(非确定性)将接收它。

请参阅语言spec

  

执行"选择"声明分几步进行:

     
      
  1. 对于语句中的所有情况,接收操作的通道操作数以及发送的通道和右侧表达式   语句在输入时按源顺序精确评估一次   "选择"声明。结果是一组要接收的通道   from或send to,以及要发送的相应值。任何一方   无论哪个(如果有的话)都会发生评估中的影响   选择通信操作以继续。表达方式   带有短变量声明的RecvStmt的左侧或   作业尚未评估。
  2.   
  3. 如果一个或多个通信可以继续,可以通过统一的伪随机选择选择可以继续进行的单个通信。   否则,如果存在默认情况,则选择该情况。如果有   没有默认情况下,"选择"声明阻止至少一个   通讯可以继续。
  4.   
  5. 除非所选案例是默认情况,否则将执行相应的通信操作。
  6.   
  7. 如果所选案例是具有短变量声明或赋值的RecvStmt,则左侧表达式为   评估并分配收到的值(或值)。
  8.   
  9. 执行所选案例的陈述清单。
  10.   

答案 1 :(得分:4)

默认情况下,goroutine通信为synchronousunbuffered:在接收方接受该值之前,发送不会完成。必须有一个接收器准备好从通道接收数据,然后发送者可以直接将其交给接收器。

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

1。通道上的发送操作会阻塞,直到接收器可用于同一频道:如果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)
}

答案 2 :(得分:0)

如果程序允许在单个频道上接收多个goroutine,则发送方正在广播。每个接收器都应具有相同的数据处理能力。因此,go运行时使用哪种机制来决定要运行Cf的许多goroutine接收器中的哪一个都没有关系。 https://github.com/golang/go/issues/247。但是,如果通道未缓冲,则每个发送的项目仅运行一个。