Are channel sends preemption points for goroutine scheduling?

时间:2015-12-10 01:47:57

标签: go scheduling channel goroutine

From my understanding of Go scheduler, Go scheduling algorithm is partially preemptive: goroutine switches happen when a goroutine is calling a function or blocking on I/O.

Does a goroutine switch happen when sending a message to a channel?

// goroutine A
ch <- message
// some additional code without function calls

// goroutine B
message := <- ch

In the code above, I want the code after ch <- message in A to be executed before switching to B, is this guaranteed? or does B get scheduled right after A sends a message on ch?

2 个答案:

答案 0 :(得分:7)

A's channel send can block, at which point it yields to the scheduler and you have no guarantee when A will receive control again. It might be after the code you're interested in in B. So the sample code has problems even with GOMAXPROCS=1.

Stepping back: when preemption happens is an implementation detail; it has changed in the past (there wasn't always a chance of preemption on function call) and may change in the future. In terms of the memory model, your program is incorrect if it relies on facts about when code executes that happen to be true today but aren't guaranteed. If you want to block some code in B from running until A does something, you need to figure out a way to arrange that using channels or sync primitives.

And as user JimB notes, you don't even need to consider preemption to run into problems with the sample code. A and B could be running simultaneously on different CPU cores, and the code after the receive in B could run while the code after the send in A is running.

答案 1 :(得分:1)

我对语言和运行时的实际理解说,如果没有你在ch <- message之后和调用goroutine B之前明确阻止,你不能保证A将在B之前完成或运行。我不知道如何这实际上已经实现了,但我也不在乎,因为我接受了面值的goroutine抽象。不要依赖程序中的巧合功能。刚刚结束你的例子,我的建议是将一个频道传递给goroutine A然后阻止等待接收它以便序列化A和B.