英文:
Go channel write ordering guarantees
问题
给定以下代码:
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
可能会先执行吗?
是否有任何参考资料可以验证这种行为在文档/代码中?
英文:
Given the following code:
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
Is it guaranteed to always print "ch1"? Or is it possible that since the ch1
is buffered and ch2
is closed right after, the second case
could run first?
And is there any reference to verify this behavior in the documentation / code?
答案1
得分: 1
写入ch1不会立即导致选择操作继续进行。在通道写入或关闭操作之后,可以调度goroutine,因此两种情况都有机会运行。如果ch1是无缓冲的,则写操作只会在通道读取之后发生,因此程序将始终打印ch1。
英文:
Writing to ch1 will not immediately cause the select operation to continue. The goroutine can be scheduled after the channel write or after the close operation so both cases have a chance to run. If ch1 was unbuffered then write operation would only happen after channel read so the program would always print ch1.
答案2
得分: 1
不,不能保证第二种情况不会发生。
当你使用通道时,通道是用于同步两个 goroutine 的理想工具,但你在操作两个独立的通道。因此,不能保证主 goroutine 对非缓冲的 ch1
通道的写操作会立即让出控制权给第二个 goroutine 的 select 语句。
在调度器将控制权让给其他 goroutine 之前,ch2
的关闭操作也可能发生,然后一个具有两个可能路径的 select 语句将随机选择。
个别证据可能让人想要相信,但在不同的负载条件下,这会导致危险的假设。
查看早期的Go调度器设计文档对于理解调度器的实现细节并没有太大帮助,因为 Go
语言的每个版本发布时,调度器的实现细节都会发生变化。
总之,需要在两个独立通道之间进行协调,以确保处理顺序的任何保证。
英文:
No, there is no guarantee that the second case may not occur.
While you are using channels - and channels are ideal for synchronizing two goroutines - you are manipulating two separate channels. So there is no guarantee that the main goroutine's write to an unbuffered ch1
channel will immediately yield control over to the second goroutine's select statement.
The close of ch2
may also occur before the scheduler yields control to other goroutines - and then a select
with two possible paths, will be chosen at random.
Anectodal evidence may be tempting to believe, but will lead to dangerous assumptions under different load conditions.
Looking at an early doc for the Go Scheduler Design doc will not be of much help as the implementation details of the schedule will literally change from release to release of the Go
language.
In closing, coordination between the two independent channels is needed to make any guarantees of the processing order.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论