在同一个 goroutines 中创建的 goroutines 是否总是按顺序执行?

Does the goroutines created in the same goroutines execute always in order?

package main

func main() {
        c:=make(chan int)
        for i:=0; i<=100;i++ {
                i:=i
                go func() {
                        c<-i
                }() 
        }   
        for {
                b:=<-c
                println(b)
                if b==100 {
                        break
                }   
        }   
}

上面的代码创建了100个goroutines将num插入通道c,所以我想知道,这些goroutines会随机执行吗?在我的测试中,输出总是 1 到 100

不,不能保证它们 运行 的顺序。使用 GOMAXPROCS=1(默认值)时,它们似乎是,但语言规范不能保证这一点。

当我 运行 你的程序 GOMAXPROCS=6 时,输出是不确定的:

$ GOMAXPROCS=6 ./test
2
0
1
4
3
5
6
7
8
9
...

在另一个 运行 上,输出略有不同。

如果您希望通道上的一组发送按顺序发生,最好的解决方案是从同一个 goroutine 执行它们。

您观察到的 "random" 行为,更严格地说,是非确定性行为。

要了解此处发生的情况,请考虑通道的行为。在这种情况下,它有很多 goroutines 试图写入通道,只有一个 goroutines 从通道中读出。

读取过程只是顺序的,我们可以忽略。

有很多并发写入进程,它们正在竞争访问共享资源(通道)。频道必须选择要接受的消息。

当通信顺序过程 (CSP) 网络做出选择时,它引入了非确定性。在 Go 中,这种选择有两种方式:

  • 并发访问通道的一端,并且
  • select 个语句。

你的情况是第一个。

CSP 是一种允许分析和理解并发行为的代数。关于此的开创性出版物是 Roscoe 和 Hoare“Occam 编程法则https://www.cs.ox.ac.uk/files/3376/PRG53.pdf(类似的想法也适用于 Go,尽管存在细微差别)。

令人惊讶的是,goroutines 的并发执行是完全确定的只有在做出选择时,非确定性才会出现。