我在有些地方看到说在系统调用和函数调用时会触发调度,于是我就写了个程序如下:
Golang
package main import "fmt" import "syscall" func test() { fmt.Println("Hello") } func preempt() { syscall.Getgid() } func main() { go test() for { preempt() } }
此时能够成功输出Hello,但是将preempt函数中的系统调用删去后就没法输出Hello了,在preempt中加入赋值语句、循环语句和fmt.Println("")
也没法输出Hello,难道只有包含系统调用的函数调用时才会触发调度吗?
Go 1.4 里面只有以下情况会触发 goroutine 调度:
runtime.Gosched
具体的实现都在 src/runtime/proc.c 里,而要完成主动抢占,Go 是采用在 stack 上做标记(
g->stackguard0 = StackPreempt
),每次函数调用的时候会检查是否需要抢占,于是要想真的抢占 goroutine CPU,只能等它调用任意一个非内联的函数。貌似 Go 会在未来版本支持真正的可抢占式调度,具体细节我不清楚。