Question on concurrent


(Jameswang2015) #1

I don’t understand why the following code output Capital letters first then followed by lower case letters while in the main file the go routine of printing lower case letters comes first before the go routine of printing upper case letters?

here is the codes:

package main

import (
	"fmt"
	"sync"
)

func main(){

	var wg = sync.WaitGroup{}
	wg.Add(2)

	go func(){
		defer wg.Done()
		printAlpha("lower")
	}()

	go func(){
		defer wg.Done()
		printAlpha("upper")
	}()

	wg.Wait()
	fmt.Println("Done")
}

func printAlpha(sign string){
	if sign == "lower"{
		for char := 'a'; char < 'a' + 26; char++{
			fmt.Printf("%c",char)
		}
	}else{
		for char := 'A'; char < 'A' + 26; char++{
			fmt.Printf("%c",char)
		}
	}
}

here is output:
ABCDEFGHIJKLabcdefghijklmnopqrMNOPQRSTUVWXYZstuvwxyzDone


Help with WaitGroup...https://play.golang.org/p/HvHQbUTT6GJ
(Sibert) #2

https://play.golang.org/p/FzeinXhtTyp


(Holloway) #3

It’s unpredictable actually. What you see on-screen is the output of all 3 goroutines chaotically smashed together.

If you’re sharp, you should notice there is a missing data flow “management” problem at the on-screen output.

SCENARIO
The current case is like having a team running a 100 yard race. Everyone starts at the same time but it’s hard to predict who runs at 8.3 mph at 4th second (t=4s) and which lane ended 1st for every matches.

In your main, you delegated 2 processes to do printAlpha respectively onto the same output. Once all 3 goroutines (main, “lower” goroutine, and “upper” goroutine) started, it’s hard to say which runs first, implementing at the moment etc, although the start time is clear that main is the first, “lower” is second, and “upper” is third. Also, keep in mind that starting a new goroutine does not guarantee that new goroutine will be scheduled immediately.

Here’s a screenshot that I ran your function with benchmark tools in my local machine. Notice each lines are not consistent. The highlighted one is the lowercase runs first.


As for goroutine technicalities. Dave wrote a very good technical article in his blog here: https://dave.cheney.net/2015/08/08/performance-without-the-event-loop.

What to do?

Plan your concurrency clearly like who is suppose to write what to output (who) at when. Then, you can ensure each goroutines works together in a synchronized manner.

Back to the 100 yard race - set up a toll booth right at the finish line then permit who and who should enter first. Then, you can guarantee the output for each lanes.