2

如果我错了,请纠正我。据我所知,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

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

编辑:添加 Scan 语句可以解决它。但是有没有更好的方法呢?

4

2 回答 2

6

当 main 退出时,无论其他 goroutine 的状态如何,程序都会终止。您可以通过添加来测试它select{}您可以通过在 main 函数的末尾这将导致 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
}
于 2013-07-28T04:13:43.583 回答
0

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

如果您运行并行 go 例程,则永远无法保证它们将以什么顺序运行。你不能让它们按顺序运行,因为它们是并行运行的!

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

于 2013-07-29T08:30:11.087 回答