在 Go 的早期版本中,当 runtime.Gosched() 被执行时,下面的代码表现出意外的行为删除:
package main import ( "fmt" "runtime" ) func say(s string) { for i := 0; i < 5; i++ { runtime.Gosched() fmt.Println(s) } } func main() { go say("world") say("hello") }
输出runtime.Gosched():
hello world hello world hello world hello world hello
不带runtime.Gosched()的输出:
hello hello hello hello hello
当Go运行时没有指定GOMAXPROCS环境变量,所有goroutine 被安排在单个操作系统线程中执行。为了使程序看起来是多线程的,Go 调度程序必须偶尔切换执行上下文。
协作多任务处理:
Go 使用协作多任务模型,这意味着 goroutine 必须显式让出控制权到其他 goroutine。这与操作系统线程中的抢占式多任务形成对比,其中调度程序透明地切换执行上下文。
runtime.Gosched() 的功能:
在没有抢占式多任务的情况下,runtime.Gosched() 允许 goroutine 将控制权交给调度程序。当一个 Goroutine 到达 Gosched 调用时,调度程序指示它将执行切换到另一个 Goroutine。
在提供的示例中,删除 Gosched 意味着执行上下文永远不会离开主例程。因此,“world”goroutine 永远不会被允许运行,并且不会打印任何“world”消息。
将 GOMAXPROCS 设置为正数(例如,runtime.GOMAXPROCS(2)) 允许 Go 创建最多该数量的本机线程。如果 GOMAXPROCS 大于 1,则可以将 goroutine 安排在不同的线程中运行,从而实现真正的并行性。
当 GOMAXPROCS 设置为 2 或以上时,示例中的 goroutine 将交错,即使没有运行时。Gosched (),演示抢占式多任务处理。
以上是为什么 `runtime.Gosched()` 对于单线程 Go 程序中交错 Goroutine 输出至关重要?的详细内容。更多信息请关注PHP中文网其他相关文章!