我在学习关于高朗的知识。
在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
我不知道为什么结果是这样。有没有人帮我?
发布于 2017-01-06 15:10:01
这是因为这一行:
runtime.GOMAXPROCS(1)因为goroutine是并发执行代码的一种方式,所以您在循环中创建的所有goroutine都必须等待proc。
由于您只有一个,并且它正忙于执行循环,因此您将有一堆goroutine等待。
当循环结束时,proc有时间执行第一个goroutine,也就是最后创建的goroutine,然后逐个对堆栈执行相同的操作,但这次是按顺序执行。
试着使用2个proc,看看会发生什么。
请记住,当您在并发工作时,代码的执行顺序是不能保证的,正如已经在注释中提到的那样。
这里你有一个序列,仅仅因为你只有一个进程。
如果您的目的是让项目按顺序处理,甚至以并发的方式处理,则应该使用通道。
让我展示一个完成这项工作的代码示例:
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()
}正如你所看到的,这只是你的的一个新版本,但是如果你执行了,你应该会得到正确的序列。
主要的变化是现在有两个goroutine,一个用于打印,一个用于循环。
两个goroutine对话通过一个int通道。
当程序开始第一个goroutin调用函数printNumbers时,该函数将等待,直到某些内容被写入通道。
然后开始第二次输出,将整数逐个写入通道。
一旦for结束,因为您只有1个进程,当通道内有项目时,printNumbers函数将再次启动。
它会循环,直到它结束项目。
当然,这里有两个循环,但你无法避免它。
因此,现在试着按您希望的方式执行进程,看看会发生什么。
发布于 2017-01-06 15:57:24
你的问题很好,答案基本上是内部运行时Go Scheduler是如何工作的,但正如Mario Santini所说的那样,执行的顺序是不能保证的。
在我有限的语言中,我可以告诉你Go Scheduler取决于内部使用的进程调度算法https://en.wikipedia.org/wiki/Scheduling_(computing),基于这一点,它将决定执行多少时间和每个goroutine请求运行的顺序,它还将根据需要为您创建操作系统线程,在您的情况下,您仅将其限制为1,因此它将根本不是parallel,所以很明显,最后一个goroutine足够幸运地将其作为第一个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
https://stackoverflow.com/questions/41500528
复制相似问题