goroutine 不再被调度

goroutine is not be scheduled again

我正在学习 golang。我有一个 goroutine 来打印变量 i,然后我写了一个死循环。但是当var i up to 491519(or some other value)时,终端没有任何输出。看起来print var i 的goroutine 不再被调度,CPU 输出491519 之后一直执行死循环。谁能告诉我原因?
谢谢。

我的代码:

package main

import (
    "fmt"
    "runtime"
)

func main() {
        go func() {
                i := 1
                for {
                        fmt.Println(i)
                        i = i + 1
                }
        }()
        runtime.GOMAXPROCS(4)
        for {
        }
}

我想补充一点:
当我在最后一个死循环中添加 fmt.Println("ABC") 时,终端上永远交替输出 ABCi

我的版本:go version go1.9.1 darwin/amd64

死循环将使用大量 CPU 并可能导致调度程序问题。如果你想阻塞一个 goroutine,从一个从未写入的通道中读取会更有效:

ch := make(chan struct{})
<-ch

或者更好的是,设置一个通道来等待关闭应用程序的信号:

stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt)
<-stop

也不需要设置GOMAXPROCS.

Goroutines 由 Go 运行时调度,因此与操作系统完成的进程调度相比存在一些限制。操作系统可以通过定时中断抢占进程,Go运行时不能抢占goroutines。

Go runtime 在 goroutine

时调度另一个 goroutine
  • 进行通道操作(这包括select语句,甚至为空)
  • 进行系统调用
  • 显式调用 runtime.Gosched

设置 GOMAXPROCS 没有多大帮助。看看下面的程序。它将使用所有处理器并将保持在紧密的繁忙循环中。

func runForever() {
   for {
   }
}

func main() {
    for i := 0; i < runtime.GOMAXPROCS(-1); i++ {
        go runForever()
    }
    time.Sleep(time.Second)
}

有几种修复程序的方法:

go func() {
    for i:= 1; true; i++ {
        fmt.Println(i)
    }
}()

for {
    runtime.Gosched()
}

go func() {
    for i:= 1; true; i++ {
        fmt.Println(i)
    }
}()

select {
}

work on improving the case of tight loops 正在进行中。