goroutine的执行顺序

时间:2019-03-01 09:41:13

标签: go

我刚接触golang。

我的理解是,所有go例程将同时执行。这两个匿名goroutine将同时开始执行。 但是当我运行此代码时,它始终会显示

a=1 first executed
a=1 second executed
panic: b != 1

不应该打印

a = 1
a = 1 first executed 
Response true
and so on

b =1 
b = 1 first executed 
Response true
and so on

自从将值发送到通道后,相应的goroutine应该阻塞并等待接收器吗?

 func main() {
            var a, b int
            var c = make(chan bool)
            go func() {
                b = 1
                fmt.Println("b=1 first executed")
                c <- true
                fmt.Println("b=1 second executed")
                if a != 1 { // impossible
                    panic("a != 1") // will never happen
                }
                fmt.Println("b=1 third executed")
            }()
            go func() {
                a = 1
                fmt.Println("a=1 first executed")
                c <- true
                fmt.Println("a=1 second executed")
                if b != 1 { // impossible
                    panic("b != 1") // will never happen
                }
                fmt.Println("a=1 third executed")
            }()

            fmt.Println("Response ", <-c)
            fmt.Println("Main executed")
            }

2 个答案:

答案 0 :(得分:0)

这两个拖曳例程之间唯一的同步是通过c上的发送完成的。由于仅从c中读取了一个值,所以两个发送操作c <- true中只有一个执行,而其他操作则永远阻塞。

让我们假设第一个goroutine首先运行(偶然),并执行send和两个Printlns,而第二个goroutine根本没有开始执行。这是一种有效的操作模式,将产生您看到的输出。

您通过c进行的同步不是不是,而是在goroutine和外部f3之间。

答案 1 :(得分:-1)

我假设您正在Playground上跑步。使用Go Playground时要记住一件事:它具有固定的时间和固定的psedo随机生成器。

这意味着,您不能使用Playground观察随机结果。 Goroutine或Go的并发概念的执行顺序通常基于统一的psedo-random-ness。

在我的终端上运行代码,会产生不同的结果:

➜  basic1 GOMAXPROCS=1 ./basic1
a=1 first executed
a=1 second executed
a=1 third executed
Response  true
Main executed
➜  basic1 GOMAXPROCS=1 ./basic1
a=1 first executed
a=1 second executed
panic: b != 1

goroutine 6 [running]:
main.main.func2(0xc000012088, 0xc000054060, 0xc0000120a0)
        /mnt/f/home/leaf/spike/stackoverflow/concur/basic1/main.go:26 +0x13b
created by main.main
        /mnt/f/home/leaf/spike/stackoverflow/concur/basic1/main.go:20 +0xed
➜  basic1 GOMAXPROCS=1 ./basic1
a=1 first executed
a=1 second executed
a=1 third executed
b=1 first executed
Response  true
Main executed

但是还有更多。正如我提到的,Go的并发执行顺序是随机的。除非有同步,否则无法保证先行。

同步包括频道通信和来自sync的内容。

您的代码中仅发生一次同步,该同步通过c进行通信。它保证了一件事:main() goroutine收到其Response时,至少在那里产生的goroutine中的一个已打印出其“被豁免”。

不能保证执行其中一个,也不执行两个或仅执行一个,也不保证goroutine是否首先命中包含if的{​​{1}}语句。< / p>

编辑:

进一步阅读: