1 回答
TA贡献1796条经验 获得超4个赞
第一个输出是由单核机器生成的输出。第二个可以由多核生成。
say是一个内部带有 for 循环的函数,它会迭代 5 次。它确实是一个普通的函数,但其中有一个调用Gosched。是什么Gosched呢,它告诉运行时暂停执行当前够程,而开始另一个等待够程。这称为屈服。
解释第一个输出
这是您可以在单核机器中获得的输出。一步一步来,
go say("world")
在这一步,运行时开始say("world")在单独的 goroutine 上执行调用并继续主 goroutine。但是机器只有一个核心。所以两个 goroutine 不能并行运行。新的 goroutine (say gr A) 必须等到正在运行的 main goroutine (say gr B) 完成或暂停(yields)。所以它等待。主协程开始执行say("hello")
现在在通过运行时的say功能gr B时会遇到runtime.Gosched()
该Gosched呼叫就像暂停。它告诉运行时暂停我并释放另一个正在等待的 goroutine。因此运行时会调度gr A. 它从它等待的地方开始,也就是,
say("world")
现在gr A执行,直到遇到自己的runtime.Gosched(). gr A停顿。gr B醒来并从它离开的地方开始奔跑。后面的语句runtime.Gosched()是打印“hello”。所以打印“你好”。gr B继续并进入其 for 循环的下一次迭代。满足Gosched。暂停。gr A重新启动。打印“世界”。我想你可以看到它是如何进行 5 次的,直到它打印出给定的输出。
解释第二个输出
如果你的机器有多个核心,goroutines 可以并行运行。你的就是你得到的输出。
现在,何时go say("world")调用gr A不必等到gr B完成。它可以立即在另一个内核上启动。所以当Gosched被调用时可能没有等待的 goroutines。如果当前的一个暂停,它将立即在不同的核心上启动。
因此,在多核机器中,您无法保证打印单词的顺序。如果您多次运行该程序,我想您也会看到其他命令。
您可以将 GOMAXPROCs 设置为 1,然后查看程序如何在单核机器上运行。
func main() {
runtime.GOMAXPROCS(1)
go say("world") // create a new goroutine
say("hello") // current goroutine
}
然后你会看到第一个输出。
- 1 回答
- 0 关注
- 121 浏览
添加回答
举报