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

时间:2015-03-15 04:21:17

标签: 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
                }   
        }   
}

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

2 个答案:

答案 0 :(得分:8)

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

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

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

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

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

答案 1 :(得分:5)

你观察到的是&#34;随机&#34;行为更严格地说是非确定性行为。

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

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

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

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

  • 并发访问某个频道的一端,
  • select陈述。

您的案例是第一个。

CSP是一种代数,可以分析和理解并发行为。关于这一点的开创性出版物是Roscoe和Hoare&#34; 奥卡姆编程法则&#34; https://www.cs.ox.ac.uk/files/3376/PRG53.pdf(类似的想法也适用于Go,尽管存在细微的差异)。

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