Go通道写排序保证



给定以下代码:

ch1 := make(chan struct{}, 1)
ch2 := make(chan struct{})
ready := make(chan struct{})
done := make(chan struct{})
go func() {
close(ready)
select {
case <-ch1:
fmt.Println("ch1")
case <-ch2:
fmr.Println("ch2")
}
}()
<-ready
ch1 <- struct{}{}
close(ch2)
<-done

是否保证总是打印"ch1"?或者,由于ch1被缓冲,ch2随后关闭,第二个case可以先运行?

在文档/代码中是否有任何参考来验证此行为?

没有,也不能保证不可能出现第二种情况。

当您使用通道(通道是同步两个程序的理想选择)时,您正在操作两个独立的通道。因此,不能保证主例程对未缓冲的ch1通道的写入将立即放弃对第二个例程的select语句的控制。

ch2的关闭也可能发生在调度程序将控制权交给其他例程之前,然后随机选择具有两个可能路径的select

轶事证据可能很容易让人相信,但在不同的负载条件下会导致危险的假设。

查看Go调度器设计文档的早期文档不会有太大帮助,因为调度的实现细节实际上会随着Go语言的发布而变化。

最后,需要两个独立通道之间的协调来保证处理顺序。

写入ch1不会立即导致选择操作继续。该例程可以安排在通道写入之后或关闭操作之后,这样两种情况都有机会运行。如果ch1没有被缓冲,那么写操作只会发生在通道读取之后,所以程序总是会打印ch1。

最新更新