去常规的奇怪行为

时间:2012-06-26 15:54:58

标签: concurrency go goroutine

我刚刚尝试了以下代码,但结果似乎有点奇怪。它首先打印奇数,然后打偶数。我真的很困惑。我原本希望它输出奇数和偶数一个接一个,就像1,2,3,4 ......谁能帮帮我?

package main

import (
    "fmt"
    "time"
)

func main() {
    go sheep(1)
    go sheep(2)
    time.Sleep(100000)
}

func sheep(i int) {
    for ; ; i += 2 {
        fmt.Println(i,"sheeps")
    }
}

2 个答案:

答案 0 :(得分:6)

您很可能只使用一个cpu线程运行。所以它运行第一个goroutine然后第二个。如果你告诉它可以在多个线程上运行,那么两者都可以同时运行,前提是操作系统在cpu上有空闲时间。您可以在运行二进制文件之前通过设置GOMAXPROCS = 2来证明这一点。或者您可以尝试在绵羊函数中添加runtime.Gosched()调用,看看是否触发运行时允许其他goroutine运行。

一般情况下,除非您使用sync.Mutex指定特定的同步点或在通道之间进行通信,否则最好不要假设两个goroutine中的操作之间的排序语义。

答案 1 :(得分:3)

非同步goroutine以完全未定义的顺序执行。如果你想打印出像

这样的东西
1 sheeps
2 sheeps
3 sheeps
....

按照确切的顺序,然后goroutines是错误的方法。当您不太关心事物发生的顺序时,并发性很有效。

您可以通过同步(在fmt.Println调用或使用频道周围锁定互斥锁)在程序中强加订单,但这是没有意义的,因为您可以更轻松地编写使用单个goroutine的代码。