通道是否为 goroutine 调度发送抢占点?

根据我对 Go 调度器的理解,Go 调度算法是部分抢占式的:当 goroutine 调用函数或阻塞 I/O 时,goroutine 切换发生。


向通道发送消息时是否会发生 goroutine 切换?


// goroutine A

ch <- message

// some additional code without function calls


// goroutine B

message := <- ch

在上面的代码中,我希望ch <- message在切换到B之前执行A之后的代码,这能保证吗?或者 B 是否在 A 发送消息后立即安排ch?


HUH函数
浏览 170回答 2
2回答

缥缈止盈

A 的通道发送可能会阻塞,此时它会交给调度程序,并且您无法保证 A 何时会再次获得控制权。它可能在您对 B 感兴趣的代码之后。因此示例代码即使使用GOMAXPROCS=1.退一步:什么时候发生抢占是一个实现细节;它在过去发生了变化(并不总是有机会抢占函数调用)并且将来可能会发生变化。就内存模型而言,如果您的程序依赖于有关代码何时执行的事实,而这些事实今天恰好是正确的,但不能保证,那么它就是不正确的。如果您想阻止 B 中的某些代码运行,直到 A 执行某些操作,您需要找到一种使用通道或sync原语来安排它的方法。正如用户 JimB 所指出的,您甚至不需要考虑抢占来遇到示例代码的问题。A 和 B 可以在不同的 CPU 内核上同时运行,并且 B 中接收之后的代码可以运行,而 A 中发送之后的代码正在运行。

子衿沉夜

我对语言和运行时的实际理解表明,如果没有ch <- message在调用 goroutine B之后和之前显式阻塞,则无法保证 A 将在 B 之前完成或运行。我不知道实际是如何实现的,但我也不知道关心,因为我从表面上接受 goroutine 抽象。不要依赖程序中的巧合功能。只是离开你的例子,我的建议是将一个通道传递给 goroutine A,然后阻塞等待接收它以序列化 A 和 B。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go