猿问

goroutines的执行顺序

我对 golang 很陌生。


我的理解是,所有的go-routines都会同时执行。两个匿名 goroutines 将同时开始执行。但是当我运行这段代码时,它总是打印出来


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")

            }


一只斗牛犬
浏览 165回答 2
2回答

慕沐林林

我假设你在 Playground 上跑步。使用 Go Playground 时要记住一件事:它有一个固定的时间和一个固定的伪随机生成器。这意味着,您不能使用 Playground 来观察随机结果。而 Goroutine 的执行顺序,或者一般来说是 Go 的并发概念,是基于统一的伪随机性。在我的终端上运行你的代码,它会产生不同的结果:➜  basic1 GOMAXPROCS=1 ./basic1a=1 first executeda=1 second executeda=1 third executedResponse  trueMain executed➜  basic1 GOMAXPROCS=1 ./basic1a=1 first executeda=1 second executedpanic: b != 1goroutine 6 [running]:main.main.func2(0xc000012088, 0xc000054060, 0xc0000120a0)        /mnt/f/home/leaf/spike/stackoverflow/concur/basic1/main.go:26 +0x13bcreated by main.main        /mnt/f/home/leaf/spike/stackoverflow/concur/basic1/main.go:20 +0xed➜  basic1 GOMAXPROCS=1 ./basic1a=1 first executeda=1 second executeda=1 third executedb=1 first executedResponse  trueMain executed但还有更多。正如我提到的,Go 的并发执行顺序是随机的。除非有同步,否则无法保证哪个先进行。同步包括通道通信和来自sync.您的代码中只发生一种同步,即通过c. 它保证了一件事:当main()goroutine 收到它时Response,至少有一个在那里生成的 goroutines 打印了它的“excecuated”。不能保证执行其中一个,也不保证执行两个或只执行一个,也不保证 goroutine 是否命中包含first 的if语句panic。

森林海

这些两个 goroutine 之间的唯一同步是通过 send on&nbsp;c。由于从 c 中只读取了一个值,因此两个发送操作中只有一个c <- true通过,而另一个永远阻塞。让我们假设第一个 goroutine 首先运行(偶然),然后执行发送和两个 Printlns,而第二个 goroutine 根本没有开始执行。这是一种有效的操作模式,将产生您看到的输出。您的同步c不是在两个匿名 goroutine 之间,而是在 goroutine 和外部 goroutine 之间f3。
随时随地看视频慕课网APP

相关分类

Go
我要回答