首页 > 解决方案 > 带时间的 Golang 协程

问题描述

我正在学习 Golang 并编写一些示例程序以熟悉不同的概念。我写了这个样例来看看 go 例程是如何工作的并遇到了这个问题。我无法弄清楚这个程序有什么问题。当 generateOddRandomNumbers() 和 geneateEvenRandomNumbers() 中的最后一行被注释掉时,它可以完美地工作。

// time.Sleep(time.Duration(val))

当我在这两个函数中取消注释该行时,输出总是错误的。

代码:

package main

import (
    "fmt"
    "math/rand"
    "time"
)

const (
    limit = 10000
)

func main() {
    rand.Seed(time.Now().UnixNano())
    go generateOddRandomNumbers(rand.Intn(9) + 1)
    go generateEvenRandomNumbers(rand.Intn(9) + 1)
    time.Sleep(1000000)
}

func generateOddRandomNumbers(count int) {
    for i := 0; i < count; i++ {
        val := rand.Intn(limit)
        if val % 2 == 0 {
            i--
            continue
        }
        fmt.Printf("Odd[%v/%v] -> %v\n", i + 1, count, val)
        // time.Sleep(time.Duration(val))
    }
}

func generateEvenRandomNumbers(count int) {
    for i := 0; i < count; i++ {
        val := rand.Intn(limit)
        if val % 2 != 0 {
            i--
            continue
        }
        fmt.Printf("Even[%v/%v] -> %v\n", i + 1, count, val)
        // time.Sleep(time.Duration(val))
    }
}

例如:良好的输出:Even() 从 1/6 打印到 6/6,Odd() 从 1/3 打印到 3/3

Even[1/6] -> 5202
Even[2/6] -> 2768
Even[3/6] -> 3020
Even[4/6] -> 6386
Even[5/6] -> 8004
Odd[1/3] -> 5075
Odd[2/3] -> 8057
Odd[3/3] -> 9655
Even[6/6] -> 8886

错误输出:(当 time.Sleep() 未注释时)在以下情况下,Even 仅从 1/9 到 3/9 打印(而不是 1/9 到 9/9)

Odd[1/1] -> 4349
Even[1/9] -> 6024
Even[2/9] -> 5444
Even[3/9] -> 6160

任何想法?

标签: gogoroutine

解决方案


Go 程序不会等待您的 go 例程完成。

  • 如果你time.Sleep在 goroutine 中注释,你的 goroutine 运行得很快,所以你得到一个完整的输出。

  • 如果你time.Sleep在 goroutine 中取消注释,你的 goroutine 运行缓慢。一旦它产生调度程序,主 go 程序就完成了,所以你的 goroutine 没有机会完成整个运行。

您可以使用channelsync.WaitGroup同步您的过程,例如如何在 Golang 中等待所有 goroutines 完成

顺便说一句,对于time.Sleep(1000000),它的单位是ns,所以在你的例子中 main go 程序快速退出。


推荐阅读