golang中的goroutine一个进程错误

时间:2017-01-06 06:55:24

标签: go goroutine

我正在研究golang。

在golang中,有一个名为goroutine的概念。我写了一个示例代码。

package main

import (
    "fmt"
    "runtime"
)

func main() {
    runtime.GOMAXPROCS(1) // cpu core를 하나만 사용하도록 해 놓음

    s := "test string"

    for i := 0; i < 100; i++ {
        go func(n int) {
            fmt.Println(s, n)
        }(i)
    }

    fmt.Scanln()
}

如果您解释代码并运行,您将看到第一个打印数据

测试字符串99

我不知道为什么会这样。有人帮我吗?

2 个答案:

答案 0 :(得分:3)

这是因为这一行:

runtime.GOMAXPROCS(1)

由于goroutine是一种同时执行代码的方法,因此在循环中创建的所有goroutine都必须等待proc。

由于你只有一个,而且它正忙于执行循环,你将会有一堆goroutine等待。

当循环结束时,proc有时间执行第一个goroutine,也就是最后创建的goroutine,然后逐个执行与堆栈相同的操作,但这次按顺序进行。< / p>

尝试放置 2 过程,看看会发生什么。

请记住,当您并发工作时,执行代码的顺序并不保证,正如评论中已经提到的那样。

这里有序列,因为你只有一个过程。

如果您的目的是以并发方式顺序处理项目,则应使用频道。

让我展示一下完成这项工作的代码示例:

package main

import (
    "fmt"
    "runtime"
)

func printNumbers(text string, ns chan int) {
    for n := range ns {
        fmt.Println(text, n)
    }
}

func main() {
    runtime.GOMAXPROCS(1) // cpu core를 하나만 사용하도록 해 놓음

    s := "test string"

    numbers := make(chan int)

    go printNumbers(s, numbers)

    go func() {
        for i := 0; i < 100; i++ {
            numbers <- i
        }
        close(numbers)
    }()

    fmt.Scanln()
}

正如您所看到的只是您的新版本,但如果您执行,则应该获得正确的序列。

主要的变化是你现在有2个goroutine,一个用于打印,一个用于循环。

通过int的渠道进行2次goroutine谈话。

当程序启动第一个goroutin时,调用函数 printNumbers ,等待直到将某些内容写入通道。

然后开始第二个gorouting,将整数逐个写入通道。

一旦for结束,因为你只有1个进程, printNumbers 函数会再次启动,因为频道内有项目。

它循环直到它结束了它。

当然,这里有2个循环,但你无法避免它。

所以现在尝试按照您的意愿进行处理,看看会发生什么。

答案 1 :(得分:0)

您的问题很好,答案基本上是内部运行时 Go Scheduler 的工作方式,但正如Mario Santini所说,执行顺序并不保证。

在我有限的话语中,我可以告诉你,Go Scheduler取决于内部使用什么类型的进程调度算法https://en.wikipedia.org/wiki/Scheduling_(computing),并根据它将决定执行的时间和每个goroutine要求的顺序运行,它也会根据需要为你创建操作系统线程,在你的情况下你只限制为1,所以它根本不是parallel,所以显然最后的goroutine很幸运足以将其作为第一个运行。

我给你留下一些更好解释的链接:

https://www.quora.com/How-does-the-golang-scheduler-work http://www.sarathlakshman.com/2016/06/15/pitfall-of-golang-scheduler http://www.slideshare.net/matthewrdale/demystifying-the-go-scheduler