简体   繁体   中英

goruntine not running concurrently?

I have the following program, I am new to gorountine, what I want to test is simple, I am calling a gorountine in a loop 100 times, it there is one time failure, the entire program fails, otherwise succeeds, and fail10Percent it delays 1 second, and check a random number if it is 4, let it fail.

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()
}

I expect the go fail10Percent(err) will run concurrently 100 times, which will only have 1 second delay, however, when I run it, I see the following result getting printed 1 second after 1 second, why is that, and how I can adjust my program to do what I want.

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

I've commented out the code for you so that you can understand.

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()
}

Update:

Simple solution without using 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) ", num)
    if num == 4 {
        ch <- 0 // Fail
        return
    }
    ch <- 1 // Pass
}

func test() {
    var ch = make(chan int, 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()
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM