【问题标题】:goroutine is not be scheduled againgoroutine 不再被调度
【发布时间】:2018-02-12 16:12:11
【问题描述】:

我正在学习 golang。我有一个 goroutine 来打印变量i,然后我写了一个死循环。但是当 var i491519(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 版本:go version go1.9.1 darwin/amd64

【问题讨论】:

  • 您的循环很忙。没有理由在您的代码中有一个繁忙的循环。
  • @JimB 谢谢你回答我。我已经设置了可以同时执行的最大 CPU 数,busy loop 和其他 goroutine 理论上应该同时执行。但是goroutine在运行一段时间后没有被调度。
  • goroutines 需要被运行时中断。没有抢占点的繁忙循环不能被抢占,因此最终会阻塞进程。这在实践中并不是一个真正的问题,因为空忙是一个编程错误,没有理由在您的代码中包含一个。

标签: go goroutine


【解决方案1】:

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

Go 运行时在 goroutine 时调度另一个 goroutine

  • 进行通道操作(这包括选择语句,甚至为空)
  • 进行系统调用
  • 显式调用 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 正在进行中。

【讨论】:

  • 哦,一个绝妙的答案!!!非常非常感谢你!我从你的回答中明白了。 ^_^
【解决方案2】:

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

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

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

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

另外应该不需要设置GOMAXPROCS

【讨论】:

  • 或者使用空的select {}语句无限期阻塞。
  • 没错,但等待信号仍然比空的select 更可取。
  • @Adrian 谢谢你回答我。我也认为这是一个调度程序错误,但我也不确定。并感谢您的其他建议,这对我有帮助。
  • @Peter 谢谢你的另一种方法。
猜你喜欢
  • 1970-01-01
  • 2019-12-03
  • 1970-01-01
  • 1970-01-01
  • 2021-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多