所以我试图在学习 Go 的同时了解并行计算的工作原理。我理解并发和并行之间的区别,但是,我有点困惑的是 Go(或操作系统)如何确定某些内容应该并行执行......
在编写代码时我必须做一些事情,还是所有事情都由调度程序处理?
在下面的示例中,我有两个函数使用 go 关键字在单独的 Go 例程中运行。因为默认的 GOMAXPROCS 是您机器上可用的处理器数量(并且我也明确设置了它),所以我希望这两个函数同时运行,因此输出将是按特定顺序排列的数字的混合 - 并且此外,每次运行的输出都会不同。然而,这种情况并非如此。相反,它们一个接一个地运行,更令人困惑的是,函数二在函数一之前运行。
代码:
func main() {
runtime.GOMAXPROCS(6)
var wg sync.WaitGroup
wg.Add(2)
fmt.Println("Starting")
go func() {
defer wg.Done()
for smallNum := 0; smallNum < 20; smallNum++ {
fmt.Printf("%v ", smallNum)
}
}()
go func() {
defer wg.Done()
for bigNum := 100; bigNum > 80; bigNum-- {
fmt.Printf("%v ", bigNum)
}
}()
fmt.Println("Waiting to finish")
wg.Wait()
fmt.Println("\nFinished, Now terminating")
}
Run Code Online (Sandbox Code Playgroud)
输出:
go run main.go
Starting
Waiting to finish
100 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Finished, Now terminating
Run Code Online (Sandbox Code Playgroud)
我正在关注这篇文章,尽管我遇到的几乎每个例子都做了类似的事情。 并发、Goroutines 和 GOMAXPROCS
这是否按照应该的方式工作,而我没有正确理解某些内容,或者我的代码不正确?
编写代码时我必须做些什么吗?
不。
或者这一切都由调度程序处理?
是的。
在下面的示例中,我有两个函数使用 go 关键字在单独的 Go 例程中运行。因为默认的 GOMAXPROCS 是您机器上可用的处理器数量(并且我也明确设置了它),所以我希望这两个函数同时运行
他们可能会也可能不会,你无法控制。
因此输出将是特定顺序的数字的混合 - 而且每次运行时输出都会不同。然而,这种情况并非如此。相反,它们一个接一个地运行,更令人困惑的是,函数二在函数一之前运行。
是的。同样,您不能强制并行计算。
你的测试是有缺陷的:你只是在每个 goroutine 中没有做太多事情。在您的示例中,goroutine 2 可能会被安排运行、开始运行并在 goroutine 1 开始运行之前完成。“启动”一个 goroutinego
并不强制它立即开始执行,所要做的只是创建一个可以运行的新 goroutine。所有可以运行的 goroutine 中的一些都被调度到您的处理器上。所有这些调度都无法控制,它是全自动的。正如您似乎知道的那样,这是并发和并行之间的区别。您可以控制 Go 中的并发性,但不能控制在两个或更多内核上实际并行执行的操作。
更实际的例子是实际的、长期运行的 goroutine,它们执行实际的工作,将显示交错的输出。