gopl-zh.github.com/ch9/ch9-08-3.md

2.0 KiB
Raw Blame History

9.8.3. GOMAXPROCS

Go的调度器使用了一个叫做GOMAXPROCS的变量来决定会有多少个操作系统的线程同时执行Go的代码。其默认的值是运行机器上的CPU的核心数所以在一个有8个核心的机器上时调度器一次会在8个OS线程上去调度GO代码。GOMAXPROCS是前面说的m:n调度中的n。在休眠中的或者在通信中被阻塞的goroutine是不需要一个对应的线程来做调度的。在I/O中或系统调用中或调用非Go语言函数时是需要一个对应的操作系统线程的但是GOMAXPROCS并不需要将这几种情况计算在内。

你可以用GOMAXPROCS的环境变量来显式地控制这个参数或者也可以在运行时用runtime.GOMAXPROCS函数来修改它。我们在下面的小程序中会看到GOMAXPROCS的效果这个程序会无限打印0和1。

for {
	go fmt.Print(0)
	fmt.Print(1)
}

$ GOMAXPROCS=1 go run hacker-cliché.go
111111111111111111110000000000000000000011111...

$ GOMAXPROCS=2 go run hacker-cliché.go
010101010101010101011001100101011010010100110...

在第一次执行时最多同时只能有一个goroutine被执行。初始情况下只有main goroutine被执行所以会打印很多1。过了一段时间后GO调度器会将其置为休眠并唤醒另一个goroutine这时候就开始打印很多0了在打印的时候goroutine是被调度到操作系统线程上的。在第二次执行时我们使用了两个操作系统线程所以两个goroutine可以一起被执行以同样的频率交替打印0和1。我们必须强调的是goroutine的调度是受很多因子影响的而runtime也是在不断地发展演进的所以这里的你实际得到的结果可能会因为版本的不同而与我们运行的结果有所不同。

** 练习9.6:** 测试一下计算密集型的并发程序练习8.5那样的会被GOMAXPROCS怎样影响到。在你的电脑上最佳的值是多少你的电脑CPU有多少个核心