Go 它是并发的,但是是什么使它并行运行呢?

Go 它是并发的,但是是什么使它并行运行呢?,go,Go,所以我在学习Go的同时,也在努力理解并行计算是如何工作的。我理解并发性和并行性之间的区别,然而,我有点困惑的是,操作系统如何决定某些东西应该并行执行 在编写代码时,我必须做些什么,还是全部由调度器处理 在下面的示例中,我有两个函数,它们使用Go关键字在单独的Go例程中运行。因为默认的GOMAXPROCS是您机器上可用的处理器数量,我也在显式地设置它,我希望这两个函数同时运行,因此输出将是特定顺序的数字的混合-而且每次运行时输出都会不同。然而,情况并非如此。相反,它们一个接一个地运行,为了让事情更

所以我在学习Go的同时,也在努力理解并行计算是如何工作的。我理解并发性和并行性之间的区别,然而,我有点困惑的是,操作系统如何决定某些东西应该并行执行

在编写代码时,我必须做些什么,还是全部由调度器处理

在下面的示例中,我有两个函数,它们使用Go关键字在单独的Go例程中运行。因为默认的GOMAXPROCS是您机器上可用的处理器数量,我也在显式地设置它,我希望这两个函数同时运行,因此输出将是特定顺序的数字的混合-而且每次运行时输出都会不同。然而,情况并非如此。相反,它们一个接一个地运行,为了让事情更加混乱,函数二在函数一之前运行

代码:

我在关注这篇文章,尽管我遇到的每个例子都有相似之处。

这是工作的方式是应该的,我没有理解正确的东西,还是我的代码不正确

当我写代码的时候,我需要做些什么

没有

还是全部由调度员处理

在下面的示例中,我有两个函数,它们使用Go关键字在单独的Go例程中运行。因为默认的GOMAXPROCS是机器上可用的处理器数量,我也在显式地设置它,所以我希望这两个函数同时运行

他们可能会也可能不会,你在这里没有控制权

因此,输出将是特定顺序的数字的混合-而且每次运行时,输出将不同。然而,情况并非如此。相反,它们一个接一个地运行,为了让事情更加混乱,函数二在函数一之前运行

对。同样,您不能强制执行并行计算

你的测试是有缺陷的:你只是没有在每个goroutine中做太多。在您的示例中,goroutine 2可能计划在goroutine 1开始运行之前运行、开始运行并完成。用go启动goroutine并不会强制它立即开始执行,所做的只是创建一个可以运行的新goroutine。从所有可以运行的goroutine中,有些被调度到您的处理器上。所有这些调度都无法控制,它是完全自动的。正如您所知,这就是并发和并行之间的区别。您可以控制Go中的并发性,但实际上在两个或多个内核上并行执行的操作并不多


更现实的例子是实际的、长时间运行的goroutine,它们执行实际工作,将显示交错输出。

所有这些都由调度器处理

由于只有两个由20条短指令组成的循环,您将很难看到并发或并行的效果

下面是另一个玩具示例:

包干管 进口 fmt 运行时 同步 同步/原子 时间 常数 ConstMaxProcs=2 ConstRunners=4 ConstLoopcount=1_000_000 func runnerid int,wg*sync.WaitGroup,cptr*int64{ var乘以整数 对于i:=0;i1{ 时代++ } 原子加法64cptr,-1 } fmt.Printf[runner%d]cptr在%d次上大于1\n,id,次 wg.完成 } func main{ runtime.GOMAXPROCSConstMaxProcs var cptr int64 wg:=&sync.WaitGroup{} wg.addconstruners 开始:=时间。现在
对于id:=1;id,您实际尝试了多少次?您的代码看起来不错。运行几次会得到不同的结果。有一篇关于go调度的非常好的文章-
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")
}
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