我刚接触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")
}
答案 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>
编辑:
进一步阅读: