为什么我的goroutine跑了一会儿就停了? 主程序包 进口( “fmt” “运行时” ) func main(){ runtime.GOMAXPROCS(1) go spinner() 常数n=45 fibN:=fib(n) fmt.Printf(“\rFibonacci(%d)=%d\n”,n,fibN) } func微调器(){ 为了{ 对于范围为“-\\\;/”的{ } } } func fib(x int)int{ 格式打印LN(x) 如果x
几秒钟后,它停止在为什么我的goroutine跑了一会儿就停了? 主程序包 进口( “fmt” “运行时” ) func main(){ runtime.GOMAXPROCS(1) go spinner() 常数n=45 fibN:=fib(n) fmt.Printf(“\rFibonacci(%d)=%d\n”,n,fibN) } func微调器(){ 为了{ 对于范围为“-\\\;/”的{ } } } func fib(x int)int{ 格式打印LN(x) 如果x,go,concurrency,goroutine,Go,Concurrency,Goroutine,几秒钟后,它停止在fib中打印x。我故意使用1处理器来理解它为什么停止。调度器是否被卡住,不再重新调度运行fib的goroutine 调度程序是否被卡住,不再重新调度运行fib的goroutine 简短回答:是的 更详细的回答:即使只有一个CPU,也不能保证会发生这种情况。系统可以自己偶尔重新安排时间。只是您正在测试它的实现没有 正如,在spinner中的硬自旋循环是。。。充其量是不友好的。它应该包含一些释放计算资源的方法,例如在时间之后或时间之后旋转.NewTicker,或者至少调用runti
fib
中打印x
。我故意使用1处理器来理解它为什么停止。调度器是否被卡住,不再重新调度运行fib
的goroutine
调度程序是否被卡住,不再重新调度运行fib的goroutine
简短回答:是的
更详细的回答:即使只有一个CPU,也不能保证会发生这种情况。系统可以自己偶尔重新安排时间。只是您正在测试它的实现没有
正如,在spinner
中的硬自旋循环是。。。充其量是不友好的。它应该包含一些释放计算资源的方法,例如在时间之后或时间之后旋转.NewTicker
,或者至少调用runtime.Gosched()
。我想你最初的旋转器是这样的,只是没有时间。NewTicker
:
func spinner() {
t := time.NewTicker(50 * time.Millisecond)
for {
for _, c := range `-\|/` {
fmt.Print(string(c), "\b")
<-t.C
}
}
}
(我将返回类型更改为int64
,希望这是显而易见的原因。)现在我们可以在0.00秒(四舍五入)内找到Fibonacci(90)=2880067194370816120
。@icza我认为这不是“当主goroutine结束时,你的应用程序也会结束”的问题,我使用运行时跟踪程序运行代码,似乎问题出在golang scheduler的fmt上。Println
在调用fib
几次之后,它从未重新调度spinner
,它可能是到期的(我很可能是错的),但go的调度器部分先发制人,而不是完全先发制人。而且fib
算法的复杂度是指数级的,所以调用fib
不会那么早返回。@GauravDhiman是的,对。Goroutine调度程序在没有显式同步的情况下是“无法控制的”。spinner()
有一个繁忙的循环,Goroutine调度程序从不切换回main
Goroutine。@gaurav dhiman,in Go≤ 1.13这根本不是先发制人。1.14应该是“几乎”抢占的第一个版本,紧循环的问题应该得到解决。注意,虽然抢占循环可能会有所改进,但繁忙循环几乎总是编程错误,应该避免。以100%的速度旋转CPU而不是使用阻塞机制很少是您想要做的。@JimB:除非有时您确实需要这样做(100%的CPU使用率不是一个问题)。我希望他们留给我们这个选择。所有的无限循环和使用朴素的递归fib
都是经过深思熟虑的,因为我试图理解它为什么会卡住,而使用更快的解决方案(或使用ticker),问题就没有发生。现在我了解到,当调度器运行微调器
goroutine时,它再也不会重新调度fib
,因为它卡在循环中。不管怎样,谢谢你的片段。
var fibcache = map[int]int64{}
func fib(x int) int64 {
if x < 2 {
return int64(x)
}
r, ok := fibcache[x]
if !ok {
r = fib(x-1) + fib(x-2)
fibcache[x] = r
}
return r
}