根据我对 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 中发送之后的代码正在运行。
子衿沉夜
TA贡献1828条经验 获得超3个赞
我对语言和运行时的实际理解表明,如果没有ch <- message
在调用 goroutine B之后和之前显式阻塞,则无法保证 A 将在 B 之前完成或运行。我不知道实际是如何实现的,但我也不知道关心,因为我从表面上接受 goroutine 抽象。不要依赖程序中的巧合功能。只是离开你的例子,我的建议是将一个通道传递给 goroutine A,然后阻塞等待接收它以序列化 A 和 B。
- 2 回答
- 0 关注
- 169 浏览
添加回答
举报
0/150
提交
取消