2 回答

TA贡献1818条经验 获得超7个赞
编写代码时我必须做些什么,
不。
还是全部由调度程序处理?
是的。
在下面的示例中,我有两个使用 go 关键字在单独的 Go 例程中运行的函数。因为默认的 GOMAXPROCS 是您机器上可用的处理器数量(我也明确设置了它)我希望这两个函数同时运行
他们可能会也可能不会,你在这里无法控制。
因此输出将是特定顺序的数字混合 - 此外,每次运行时输出都会不同。然而,这种情况并非如此。相反,它们一个接一个地运行,更令人困惑的是,功能二在功能一之前运行。
是的。同样,您不能强制并行计算。
你的测试是有缺陷的:你只是在每个 goroutine 中做的不多。在您的示例中,goroutine 2 可能被安排在 goroutine 1 开始运行之前运行、开始运行并完成。“启动”一个 goroutinego
并不强制它立即开始执行,所做的只是创建一个可以运行的新 goroutine。从所有可以运行的 goroutine 中,一些被调度到你的处理器上。所有这些调度都无法控制,它是全自动的。如您所知,这是并发和并行之间的区别。您可以控制 Go 中的并发性,但不能(太多)控制在两个或更多内核上实际并行完成的工作。
具有实际工作的长期运行的 goroutine 的更实际示例将显示交错输出。

TA贡献1844条经验 获得超8个赞
这一切都由调度程序处理。
只有 20 条短指令的两个循环,您将很难看到并发或并行的效果。
这是另一个玩具示例: https: //play.golang.org/p/xPKITzKACZp
package main
import (
"fmt"
"runtime"
"sync"
"sync/atomic"
"time"
)
const (
ConstMaxProcs = 2
ConstRunners = 4
ConstLoopcount = 1_000_000
)
func runner(id int, wg *sync.WaitGroup, cptr *int64) {
var times int
for i := 0; i < ConstLoopcount; i++ {
val := atomic.AddInt64(cptr, 1)
if val > 1 {
times++
}
atomic.AddInt64(cptr, -1)
}
fmt.Printf("[runner %d] cptr was > 1 on %d occasions\n", id, times)
wg.Done()
}
func main() {
runtime.GOMAXPROCS(ConstMaxProcs)
var cptr int64
wg := &sync.WaitGroup{}
wg.Add(ConstRunners)
start := time.Now()
for id := 1; id <= ConstRunners; id++ {
go runner(id, wg, &cptr)
}
wg.Wait()
fmt.Printf("completed in %s\n", time.Now().Sub(start))
}
与您的示例一样:您无法控制调度程序,此示例只是有更多“表面”来见证并发的一些影响。
很难从程序内部看到并发性和并行性之间的实际差异,您可以在处理器运行时查看处理器的活动,或检查全局执行时间。
Playground 的时钟不提供亚秒级精度,如果您想查看实际时间,请将代码复制/粘贴到本地文件中并调整常量以查看各种效果。
请注意,其他一些影响(可能:if val > 1 {...}检查的分支预测和/或共享变量周围的内存失效cptr)使我的机器上的执行非常不稳定,所以不要指望直接“使用 ConstMaxProcs = 4 运行比快 4 倍ConstMaxProcs = 1"。
- 2 回答
- 0 关注
- 142 浏览
添加回答
举报