goroutine内调用函数时会不会触发调度?
我在有些地方看到说在系统调用和函数调用时会触发调度,于是我就写了个程序如下:
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,难道只有包含系统调用的函数调用时才会触发调度吗?
右·菲利普
10 years ago
Answers
Go 1.4 里面只有以下情况会触发 goroutine 调度:
- syscall
- C 函数调用(本质上与 syscall 一样)
- 等待各种锁、chan
-
主动调用
runtime.Gosched
- 某个 goroutine 的调用时间超过 100 ms,并且这个 goroutine 调用了非内联的函数
具体的实现都在
src/runtime/proc.c
里,而要完成主动抢占,Go 是采用在 stack 上做标记(
g->stackguard0 = StackPreempt
),每次函数调用的时候会检查是否需要抢占,于是要想真的抢占 goroutine CPU,只能等它调用任意一个非内联的函数。
貌似 Go 会在未来版本支持真正的可抢占式调度,具体细节我不清楚。
旧就留就留
answered 10 years ago