我正在研究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
我不知道为什么会这样。有人帮我吗?
答案 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