goruntine不能同时运行?

问题描述

我有以下程序,我是gorountine的新手,我要测试的很简单,我在一个循环中调用gorountine 100次,它一次失败,整个程序失败,否则成功,并且fail10Percent会延迟1秒钟,然后检查随机数是否为4,让它失败。

package main

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

func fail10Percent(ch chan int) {
    time.Sleep(1 * time.Second)
    e := rand.Intn(10)
    fmt.Println("Calculating rand.Intn(10) ",e)

    if e == 4 {
        ch <- 0
        return
    }
    ch <- 1
}

func test() {
    for i := 0; i < 100; i++ {
        err := make(chan int)
        go fail10Percent(err)

        res := <-err

        fmt.Println("=== result: ",res)

        if res != 1 {
            fmt.Println("failed")
            return
        }
    }
    fmt.Println("succeeded")
}

func main() {
    test()
}

我希望go fail10Percent(err)可以同时运行100次,只有1秒的延迟,但是,当我运行它时,我看到以下结果在1秒后打印1秒,为什么?如何调整程序以执行自己想要的操作。

Calculating rand.Intn(10)  1
=== result:  1
Calculating rand.Intn(10)  7
=== result:  1
Calculating rand.Intn(10)  7
=== result:  1
Calculating rand.Intn(10)  9
=== result:  1
Calculating rand.Intn(10)  1
=== result:  1
Calculating rand.Intn(10)  8
=== result:  1
Calculating rand.Intn(10)  5
=== result:  1
Calculating rand.Intn(10)  0
=== result:  1
Calculating rand.Intn(10)  6
=== result:  1
Calculating rand.Intn(10)  0
=== result:  1
Calculating rand.Intn(10)  4
=== result:  0
failed

解决方法

我已为您注释了代码,以便您理解。

package main

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

func fail10Percent(ch chan int,w *sync.WaitGroup) {
    defer w.Done()
    num := rand.Intn(10)
    fmt.Println("calculating rand.Intn(10) ",num)
    if num == 4 {
        ch <- 0 // Fail
        return
    }
    ch <- 1 // Pass
}

func test() {
    var ch = make(chan int,1)
    // Launch the receiver goroutine to listen if goroutine succeeded or failed based on the value sent to ch
    go func() {
        for recv := range ch {
            switch recv {
            // Fail
            case 0:
                fmt.Println("goroutine failed")
            // Pass
            case 1:
                fmt.Println("goroutine succeed")
            }
        }
    }()
    // wg is a WaitGroup
    var wg sync.WaitGroup
    for i := 0; i < 100; i++ {
        wg.Add(1)
        go fail10Percent(ch,&wg)
    }
    // wg.Wait() to wait for all goroutines to complete
    wg.Wait()
    // Close the channel so that the receiver can stop
    close(ch)
}

func main() {
    test()
}

更新:

不使用sync.WaitGroup

的简单解决方案
package main

import (
    "fmt"
    "math/rand"
)

// Using a send only channel
func fail10Percent(ch chan<- int) {
    num := rand.Intn(10)
    fmt.Println("calculating rand.Intn(10) ",1)
    for i := 0; i < 100; i++ {
        go fail10Percent(ch)
    }
    for i := 0; i < 100; i++ {
        if recv := <-ch; recv == 0 {
            fmt.Println("goroutine failed")
        } else if recv == 1 {
            fmt.Println("goroutine succeed")
        }
    }
    close(ch)
}

func main() {
    test()
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...