为了账号安全,请及时绑定邮箱和手机立即绑定

goroutines的执行顺序

goroutines的执行顺序

Go
一只斗牛犬 2023-06-12 15:28:40
我对 golang 很陌生。我的理解是,所有的go-routines都会同时执行。两个匿名 goroutines 将同时开始执行。但是当我运行这段代码时,它总是打印出来a=1 first executeda=1 second executedpanic: b != 1不应该打印吗a = 1a = 1 first executed Response trueand so on或者b =1 b = 1 first executed Response trueand 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 回答

?
慕沐林林

TA贡献2016条经验 获得超9个赞

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


这意味着,您不能使用 Playground 来观察随机结果。而 Goroutine 的执行顺序,或者一般来说是 Go 的并发概念,是基于统一的伪随机性。


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


➜  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,至少有一个在那里生成的 goroutines 打印了它的“excecuated”。


不能保证执行其中一个,也不保证执行两个或只执行一个,也不保证 goroutine 是否命中包含first 的if语句panic。


查看完整回答
反对 回复 2023-06-12
?
森林海

TA贡献2011条经验 获得超2个赞

这些两个 goroutine 之间的唯一同步是通过 send on c。由于从 c 中只读取了一个值,因此两个发送操作中只有一个c <- true通过,而另一个永远阻塞。

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

您的同步c不是两个匿名 goroutine 之间,而是在 goroutine 和外部 goroutine 之间f3


查看完整回答
反对 回复 2023-06-12
  • 2 回答
  • 0 关注
  • 164 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信