【问题标题】:Strange behavior of go routinegoroutine的奇怪行为
【发布时间】:2012-06-26 15:54:58
【问题描述】:

我刚刚尝试了以下代码,但结果似乎有点奇怪。它先打印奇数,然后打印偶数。我真的很困惑。我希望它一个接一个地输出奇数和偶数,就像 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")
    }
}

【问题讨论】:

  • 如果您正在寻求帮助,您至少可以用描述性的方式命名和标记您的问题。

标签: concurrency go goroutine


【解决方案1】:

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

一般来说,最好不要假设两个 goroutine 中的操作之间的顺序语义,除非您使用 sync.Mutex 指定特定的同步点或在它们之间通过通道进行通信。

【讨论】:

  • 我不认为他是在假设一个排序,而是希望看到两个进程同时运行,而不是显然一个接一个地运行。我的猜测是它应该是一个简单的测试来看看 goroutine 的酷炫程度。在这种情况下,每次打印后稍作睡眠也可能会起到作用,尽管它显然会减慢速度。
  • 当然,但是对于在尝试调试 goroutines 时发现这个问题的任何人来说,这是有用的建议,所以我把它扔进去了。
【解决方案2】:

未同步的 goroutine 以完全未定义的顺序执行。如果你想打印出类似的东西

1 sheeps
2 sheeps
3 sheeps
....

按照这个确切的顺序,goroutines 是错误的方法。当您不太关心事情发生的顺序时,并发性很好。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-25
    • 1970-01-01
    • 2021-06-08
    相关资源
    最近更新 更多