Gosched之外还有什么?

时间:2018-09-29 16:34:46

标签: go

下面的代码段

package main

import (
        "fmt"
        "runtime"
)

func main() {
        runtime.GOMAXPROCS(1)
        var s string
        done := make(chan bool)
        go func() {
                fmt.Scanln(&s)
                fmt.Println(s)
                done <- true
        }()

        var i int
        for i = 0; i < 1e10; i++ {
        }
        fmt.Println(i)
        <-done
}

运行它,快速输入几个字符,例如abcd循环结束前的for;最后点击Enter。据我所知,for循环中没有Gosched可以将主goroutine切换到子例程的屈服点,为什么迅速打印abcd甚至在for循环结束之前?

abcd10000000000

abcd

2 个答案:

答案 0 :(得分:1)

您无法预测输出是随机的。因为在您的情况下,go例程将运行,然后执行for循环。现在,如果go例程在for循环完成其迭代之前完成,则它将首先在go例程中打印该值,然后在done通道上发送该值,然后它将打印i的值。 done通道将等待,直到go例程在其上发送了值。

例如,如果您尝试仅扫描as然后快速输入,则您的值将首先在go例程中打印,然后10000000000将在最后一个例程中打印,因此取决于go例程是否将在执行之前执行for循环完成。

运行时可以分配比GOMAXPROCS的值更多的线程来服务多个未完成的I / O请求。 GOMAXPROCS仅影响一次实际可以执行多少个goroutine;系统调用中可能会任意阻止更多内容。

答案 1 :(得分:0)

代码按预期运行,

每个正在运行的程序都可以访问三个文件,stdinstdoutstderr

您在终端中键入的所有内容都是您写入stdin文件,程序输出也写入stdout

在您的情况下,您已将一些数据写入stdin,正在读取和显示。

如果您甚至在进程开始处理输入之前就已经写了一些数据,那也是一样,从文件读取。

基本上,只要程序启动并获得足够的输入,它就会继续进行,如果它没有机会执行,直到有人读取输入,它仍然位于stdin中。

由于GOMAXPROCS并不意味着您将只运行一个goroutine,如果该goroutine被阻止,则会创建一个新的goroutine。 GOMAXPROCS表示在任何时间实例中只能运行一个用户线程。