Golang go routine run, but different from what i expected

86 views Asked by At

so i have this simple go routine code

func jobX(wg *sync.WaitGroup)  {
    defer wg.Done()
    for i := 0; i < 5; i++ {
        fmt.Println("routine X: ", i)
        if i == 2 {
            time.Sleep(3 * time.Second)
        }
    }
}

func jobY()  {
    for i := 0; i < 5; i++ {
        fmt.Println("routine Y: ", i)
    }
}

func main() {

    var wg sync.WaitGroup

    fmt.Println("starting go routine...")

    wg.Add(1)
    go jobX(&wg)
    jobY()

    fmt.Println("end")

    wg.Wait()
}

when i run the program, this is the result:

starting go routine...
routine Y: 0
routine Y: 1
routine Y: 2
routine Y: 3
routine Y: 4
end
routine X: 0
routine X: 1
routine X: 2
routine X: 3
routine X: 4

but this is what i expect it to be:

starting go routine...
routine X: 0
routine X: 1
routine X: 2
routine Y: 0
routine Y: 1
routine Y: 2
routine Y: 3
routine Y: 4
routine X: 3
routine X: 4
end

i cant figure it out how should i change my code to get this result.

2

There are 2 answers

0
smathy On

You need a second increment of your waitGroup for your Y, and then you also need to move the Wait up before the "end":

    var wg sync.WaitGroup

    fmt.Println("starting go routine...")

    wg.Add(1)
    go jobX(&wg)

    wg.Add(1)
    go jobY(&wg)

    wg.Wait()

    fmt.Println("end")

...and make the corresponding changes to your jobY func so it can call wg.Done() like jobX is.

0
bdparrish On

If you are looking to ensure that end is called after everything is run, then you need to move the wg.Wait() to in front of your fmt.Println("end"):

func main() {

    var wg sync.WaitGroup

    fmt.Println("starting go routine...")

    wg.Add(1)
    go jobX(&wg)
    jobY()

    wg.Wait() // <-- change

    fmt.Println("end")
}

You cannot expect a specific output when using goroutines.

Check out this blog post for more information.