为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
HUH函数 2021-11-29 15:42:11
根据我对 Go 调度器的理解,Go 调度算法是部分抢占式的:当 goroutine 调用函数或阻塞 I/O 时,goroutine 切换发生。向通道发送消息时是否会发生 goroutine 切换?// goroutine Ach <- message// some additional code without function calls// goroutine Bmessage := <- ch在上面的代码中,我希望ch <- message在切换到B之前执行A之后的代码,这能保证吗?或者 B 是否在 A 发送消息后立即安排ch?
查看完整描述

2 回答

?
缥缈止盈

TA贡献2041条经验 获得超4个赞

A 的通道发送可能会阻塞,此时它会交给调度程序,并且您无法保证 A 何时会再次获得控制权。它可能在您对 B 感兴趣的代码之后。因此示例代码即使使用GOMAXPROCS=1.

退一步:什么时候发生抢占是一个实现细节;它在过去发生了变化(并不总是有机会抢占函数调用)并且将来可能会发生变化。就内存模型而言,如果您的程序依赖于有关代码何时执行的事实,而这些事实今天恰好是正确的,但不能保证,那么它就是不正确的。如果您想阻止 B 中的某些代码运行,直到 A 执行某些操作,您需要找到一种使用通道或sync原语来安排它的方法。

正如用户 JimB 所指出的,您甚至不需要考虑抢占来遇到示例代码的问题。A 和 B 可以在不同的 CPU 内核上同时运行,并且 B 中接收之后的代码可以运行,而 A 中发送之后的代码正在运行。


查看完整回答
反对 回复 2021-11-29
?
子衿沉夜

TA贡献1828条经验 获得超3个赞

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


查看完整回答
反对 回复 2021-11-29
  • 2 回答
  • 0 关注
  • 169 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信