为什么我的 goroutine 在几分钟 运行 后停止了?
Why my goroutine stopped after a few moments running?
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 个处理器来理解它停止的原因。调度程序是否卡住了并且不再重新调度 goroutine 运行 和 fib
?
Is the scheduler stuck and not rescheduling the goroutine running the fib anymore?
简答:是。
更长的答案:您无法保证这会发生,即使只有一个 CPU。系统可以偶尔自行重新安排时间。只是您正在测试它的实现没有。
与 一样,您在 spinner
中拥有的那种硬自旋循环是......充其量是不友好的。它应该包含一些释放计算资源的方法,例如用time.After
或time.NewTicker
旋转,或者至少调用runtime.Gosched()
。我想你原来的 spinner
是这样的,只是没有 time.NewTicker
:
func spinner() {
t := time.NewTicker(50 * time.Millisecond)
for {
for _, c := range `-\|/` {
fmt.Print(string(c), "\b")
<-t.C
}
}
}
有了自动收报机,微调器旋转得非常快,但程序完成了(尽管没有缓存 fib
)。当然,更聪明的 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
}
(出于明显的原因,我将 return 类型更改为 int64
。)现在我们可以在 0.00 秒(四舍五入)内找到 Fibonacci(90) = 2880067194370816120
。
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 个处理器来理解它停止的原因。调度程序是否卡住了并且不再重新调度 goroutine 运行 和 fib
?
Is the scheduler stuck and not rescheduling the goroutine running the fib anymore?
简答:是。
更长的答案:您无法保证这会发生,即使只有一个 CPU。系统可以偶尔自行重新安排时间。只是您正在测试它的实现没有。
与 spinner
中拥有的那种硬自旋循环是......充其量是不友好的。它应该包含一些释放计算资源的方法,例如用time.After
或time.NewTicker
旋转,或者至少调用runtime.Gosched()
。我想你原来的 spinner
是这样的,只是没有 time.NewTicker
:
func spinner() {
t := time.NewTicker(50 * time.Millisecond)
for {
for _, c := range `-\|/` {
fmt.Print(string(c), "\b")
<-t.C
}
}
}
有了自动收报机,微调器旋转得非常快,但程序完成了(尽管没有缓存 fib
)。当然,更聪明的 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
}
(出于明显的原因,我将 return 类型更改为 int64
。)现在我们可以在 0.00 秒(四舍五入)内找到 Fibonacci(90) = 2880067194370816120
。