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

MacOS 和 Linux 上 go1.5beta2 的不同行为

MacOS 和 Linux 上 go1.5beta2 的不同行为

Go
侃侃无极 2021-10-25 16:29:04
该示例取自“围棋之旅”:https : //tour.golang.org/concurrency/1显然,程序输出应该有 10 行:5 行代表“hello”,5 行代表“world”。但我们有:Linux - 9 行MacOS - 10 行Linux 输出(9 行):$ go run 1.go helloworldhelloworldhelloworldworldhellohelloMacOS X 输出(10 行):$ go run 1.go helloworldworldhellohelloworldhelloworldhelloworld任何人都可以解释 -为什么?Linux uname -a:Linux desktop 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt11-1 (2015-05-24) x86_64 GNU/LinuxmacOS 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 mainimport (    "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")}
查看完整描述

1 回答

?
慕工程0101907

TA贡献1887条经验 获得超5个赞

从规范:


程序执行首先初始化主包,然后调用函数main。当该函数调用返回时,程序退出。它不会等待其他(非main)goroutine 完成。


所以不能保证 goroutine 打印"world"有时间在程序退出之前完成。


我怀疑如果你运行程序足够多,你会在两个平台上看到 9 行和 10 行输出。将GOMAXPROCS环境变量设置为 2 也可能有助于触发问题。


您可以通过使主 goroutine 显式等待另一个 goroutine 完成来修复它。例如,使用频道:


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

}

我已经向通道添加了一个缓冲区,以便say函数可以在不阻塞的情况下发送值(主要是为了"hello"调用实际返回)。然后我等待从通道接收两个值以确保两个调用都已完成。


对于更复杂的程序,该sync.WaitGroup类型可以提供一种更方便的方式来等待多个 goroutine。


查看完整回答
反对 回复 2021-10-25
  • 1 回答
  • 0 关注
  • 181 浏览
慕课专栏
更多

添加回答

举报

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