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

huangapple go评论66阅读模式
英文:

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个goroutine来将数字插入通道c中,所以我想知道这些goroutine是否会以随机顺序执行?在我的测试中,输出总是从1到100。

英文:
package main

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

The above code created 100 goroutines to insert num to channel c, so I just wonder that, will these goroutines execute in random orders? During my test, the output will always be 1 to 100

答案1

得分: 9

不,它们不能保证按顺序运行。在GOMAXPROCS=1(默认值)的情况下,它们似乎是按顺序运行的,但这在语言规范中并没有保证。

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

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

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

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

英文:

No, they are not guaranteed to run in order. With GOMAXPROCS=1 (the default) they appear to, but this is not guaranteed by the language spec.

And when I run your program with GOMAXPROCS=6, the output is non-deterministic:

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

On another run, the output was slightly different.

If you want a set of sends on a channel to happen in order, the best solution would be to perform them from the same goroutine.

答案2

得分: 5

你所观察到的“随机”行为,更准确地说是非确定性行为。

要理解这里发生的情况,考虑一下通道的行为。在这种情况下,有许多goroutine试图写入通道,而只有一个goroutine从通道中读取。

读取过程只是简单的顺序执行,我们可以忽略它。

有许多并发的写入过程,它们竞争访问一个共享资源(通道)。通道必须对它将接受的消息进行选择。

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

  • 并发访问通道的其中一个端点
  • select语句

你的情况是第一种情况。

CSP是一种允许并发行为进行分析和理解的代数。关于这方面的一个重要出版物是Roscoe和Hoare的《Occam编程法则》(https://www.cs.ox.ac.uk/files/3376/PRG53.pdf)(类似的思想也适用于Go语言,尽管存在一些小差异)。

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

英文:

What you observe as "random" behaviour is, more strictly, non-deterministic behaviour.

To understand what is happening here, think about the behaviour of the channel. In this case, it has many goroutines trying to write into the channel, and just one goroutine reading out of the channel.

The reading process is simply sequential and we can disregard it.

There are many concurrent writing processes and they are competing to access a shared resource (the channel). The channel has to make choices about which message it will accept.

When a Communicating Sequential Process (CSP) network makes a choice, it introduces non-determinism. In Go, there are two ways that this kind of choice happens:

  • concurrent access to one of the ends of a channel, and
  • select statements.

Your case is the first of these.

CSP is an algebra that allows concurrent behaviours to be analysed and understood. A seminal publication on this is Roscoe and Hoare "The Laws of Occam Programming" https://www.cs.ox.ac.uk/files/3376/PRG53.pdf (similar ideas apply to Go also, although there are small differences).

Surprisingly, the concurrent execution of goroutines is fully deterministic. It's only when choices are made that non-determinism comes in.

huangapple
  • 本文由 发表于 2015年3月15日 12:21:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/29057210.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定