为什么我的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
}