在相同的goroutine中创建的goroutine是否始终按顺序执行?

vze*_*zex 3 go goroutine

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
                }   
        }   
}
Run Code Online (Sandbox Code Playgroud)

上面的代码创建了100个goroutine来插入num到通道c,所以我只是想知道,这些goroutines会以随机顺序执行吗?在我的测试期间,输出将始终为1到100

Jam*_*dge 9

不,他们不能保证按顺序运行.使用GOMAXPROCS=1(默认值)它们会出现,但语言规范无法保证这一点.

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

$ GOMAXPROCS=6 ./test
2
0
1
4
3
5
6
7
8
9
...
Run Code Online (Sandbox Code Playgroud)

在另一次运行中,输出略有不同.

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


Ric*_*777 5

您观察到的"随机"行为更严格地说是非确定性行为.

要了解此处发生的事情,请考虑频道的行为.在这种情况下,它有许多尝试写入通道的goroutine,只有一个goroutine读出通道.

阅读过程简单顺序,我们可以忽略它.

有许多并发写入过程,它们竞争访问共享资源(通道).频道必须选择接受哪条消息.

当通信顺序进程(CSP)网络做出选择时,它会引入非确定性.在Go中,有两种方式可以实现这种选择:

  • 并发访问一个通道的一端,和
  • select 声明.

你的案子是第一个.

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

令人惊讶的是,goroutine的并发执行是完全确定的.这是只有当选择由非确定性的用武之地.