例子取自《围棋之旅》:https://tour.golang.org/concurrency/1
显然,程序输出应该有 10 行:5 行用于“hello”,5 行用于“world”。
但是我们有:
- Linux - 9 行
- MacOS - 10 行
Linux 输出(9 行):
$ go run 1.go
hello
world
hello
world
hello
world
world
hello
hello
MacOS X 输出(10 行):
$ go run 1.go
hello
world
world
hello
hello
world
hello
world
hello
world
谁能解释一下 - 为什么?
Linux uname -a
:
Linux desktop 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt11-1 (2015-05-24) x86_64 GNU/Linux
MacOS X uname -a
:
Darwin 14.5.0 Darwin Kernel Version 14.5.0: Thu Jul 9 22:56:16 PDT 2015; root:xnu-2782.40.6~1/RELEASE_X86_64 x86_64
旅游源代码:
package main
import (
"fmt"
"time"
)
func say(s string) {
for i := 0; i < 5; i++ {
time.Sleep(1000 * time.Millisecond)
fmt.Println(s)
}
}
func main() {
go say("world")
say("hello")
}
最佳答案
来自 the specification :
Program execution begins by initializing the main package and then invoking the function
main
. When that function invocation returns, the program exits. It does not wait for other (non-main
) goroutines to complete.
因此无法保证 goroutine 打印 "world"
有时间在程序退出之前完成。
我怀疑如果您运行该程序足够多次,您将在两个平台上同时看到 9 行和 10 行输出。将 GOMAXPROCS
环境变量设置为 2 也可能有助于触发问题。
您可以通过让主 goroutine 显式等待另一个 goroutine 完成来修复它。例如,使用 channel :
func say(s string, done chan<- bool) {
for i := 0; i < 5; i++ {
time.Sleep(1000 * time.Millisecond)
fmt.Println(s)
}
done <- true
}
func main() {
c := make(chan bool, 2)
go say("world", c)
say("hello", c)
<-c
<-c
}
我已经向 channel 添加了一个缓冲区,以便 say
函数可以发送一个值而不阻塞(主要是 "hello"
调用实际返回)。然后我等待从 channel 接收两个值以确保两个调用都已完成。
对于更复杂的程序,sync.WaitGroup
type 可以提供一种更方便的方式来等待多个 goroutines。
关于linux - go1.5beta2 在 MacOS 和 Linux 上的不同行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31597096/