奇怪的Goroutines行为

时间:2013-07-28 04:04:46

标签: go goroutine

如果我错了,请纠正我。只要我知道,goroutine的工作方式大致类似于线程。所以如果我用不同的参数生成相同的函数,前缀为go。它应该工作得很好吗?

package main

import "fmt"


func f(from string) {
    for i := 0; i < 3; i++ {
        fmt.Println(from, ":", i)
    }
}

func main() {
    go f("direct")
    go f("redirect")
    //var input string
    //fmt.Scanln(&input)

}

实际输出:

rahul@g3ck0:~/programs/go$ go run goroutine.go 
rahul@g3ck0:~/programs/go$ 

我刚回来提示。

预期产出:

direct : 0
direct : 1
direct : 2
redirect : 0
redirect : 1
redirect : 2

不一定是相同的顺序 无法理解这种奇怪的行为。我错过了什么吗?

编辑:添加扫描语句会解决它。但有没有更好的方法呢?

2 个答案:

答案 0 :(得分:6)

当主要退出时,无论其他goroutines的状态如何,程序都会终止。您可以通过在主函数末尾添加select{}来测试此项。这将导致main永远不会退出,您将看到其他goroutines运行。

如果你希望你的程序在两个goroutine完成时干净地退出(没有死锁),你需要使用类似通道或sync.Waitgroup的东西来协调一切都完成时的主要结局。

使用sync.Waitgroup的示例:

package main

import (
    "fmt"
    "sync"
)

func f(from string, wg *sync.WaitGroup) {
    for i := 0; i < 3; i++ {
        fmt.Println(from, ":", i)
    }

    wg.Done()
}

func main() {
    wg := new(sync.WaitGroup)
    wg.Add(2)

    go f("direct", wg)
    go f("redirect", wg)

    wg.Wait()
}

使用频道的示例:

package main

import (
    "fmt"
)

func f(from string, ch chan<- bool) {
    for i := 0; i < 3; i++ {
        fmt.Println(from, ":", i)
    }

    ch <- true
}

func main() {
    ch := make(chan bool)

    go f("direct", ch)
    go f("redirect", ch)

    <-ch
    <-ch
}

答案 1 :(得分:0)

如上所述,最后的select {}确保显示输出,但您不能指望go例程以特殊顺序运行。

如果您运行parallell go例程,则无法保证它们将以何种顺序运行。除了它们之外,你不能按顺序运行,因为它们是并行运行的!

您可能会在一台机器上获得预期的输出时间,但不能保证每次在任何给定的机器上打印输出都是有序的!!