【发布时间】:2020-01-04 10:43:45
【问题描述】:
package main
import (
"fmt"
"runtime"
)
func main() {
runtime.GOMAXPROCS(1)
go spinner()
const n = 45
fibN := fib(n)
fmt.Printf("\rFibonacci(%d) = %d\n", n, fibN)
}
func spinner() {
for {
for _ = range `-\|/` {
}
}
}
func fib(x int) int {
fmt.Println(x)
if x < 2 {
return x
}
return fib(x-1) + fib(x-2)
}
几秒钟后,它停止在fib 中打印x。我故意使用 1 个处理器来了解它为什么停止。调度器是否卡住并且不再重新调度运行fib 的goroutine?
【问题讨论】:
-
@icza 我认为这不是“当主 goroutine 结束时,您的应用程序也会结束”的问题,我使用运行时跟踪器运行代码,似乎问题是带有
fmt.Println的 golang 调度程序在几次致电fib之后,永远不要重新安排spinner,这可能是到期的(我很可能是错的),但go 的调度程序部分地抢占式并不完全。此外,fib算法具有指数复杂度,因此调用fib不会那么早返回。 -
@GauravDhiman 是的,对。没有显式同步的 Goroutine 调度是“无法控制的”,
spinner()有一个繁忙的循环,goroutine 调度程序永远不会切换回maingoroutine。 -
@gaurav-dhiman,在 Go ≤ 1.13 中,它根本不是抢占式的。 1.14应该是第一个发布的时候“差不多”抢占式了,紧循环的问题应该解决了。
-
请注意,虽然可能会出现抢占循环的改进,但繁忙的循环几乎总是一个编程错误,应该避免。以 100% 的速度旋转 CPU 而不是使用阻塞机制很少是您想要做的。
-
@JimB:除了有时您确实需要这样做(并且 100% 的 CPU 使用率不是问题)。我希望他们给我们留下这个选择。
标签: go concurrency goroutine