With todays multicore processors writing concurrent code is very beneficial and the designers of Golang have made the concurrency model in Golang extremely easy and simple to implement in your code, as we will now see in the example below.
Just a note on the above mention of multicore CPU’s. Just because the system has more than 1 core and you write concurrent code it does not necessarily mean it will run across more than one core. To see why this is and to also understand why ‘Concurrency Is Not Parallelism’ you should watch Rob Pikes talk here. Heck even if you don’t plan on programming Go you should probably watch it anyway.
Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
package main import ( "fmt" "sync" "time" ) func f(wg *sync.WaitGroup, val string) { time.Sleep(3 * time.Second) //Sleep a few secs fmt.Printf("Finished: %v - %v\n", val, time.Now()) wg.Done() } func main() { var wg sync.WaitGroup wg.Add(3) //We need to wait for 3 calls to 'done' on this wait group go f(&wg, "goroutine A") //Call function f concurrently //Anonymous func / closure go func(wg *sync.WaitGroup, val string) { time.Sleep(3 * time.Second) //Sleep a few secs fmt.Printf("Finished: %v - %v\n", val, time.Now()) wg.Done() }(&wg, "goroutine B") //Call Anonymous function concurrently go f(&wg, "goroutine C") //Call function f concurrently wg.Wait() //Wait for the concurrent routines to call 'done' fmt.Printf("Finished all goroutines: %v\n", time.Now()) } |
Code analysis
Calling a function concurrently is really simple. We just use the ‘go’ keyword before the call
1 |
go f(&wg,"goroutine C") |
However usually we when we have multiple things happening concurrently we want to make sure that the individual processes synchronize together at some point in the programs execution.
For example in a web page backed by a database, we might want to make multiple database queries concurrently, but we need to wait until they have all returned their datasets before we render the data in HTML and send the page over the wire to the user.
Fortunately this is quite easy using the Sync package
First we define how many go routines we will be waiting for until we release the block
1 |
wg.Add(3) |
Then at the end of our concurrent go routine we need to tell sync that we have completed one of the tasks, which will decrement the waiting counter.
1 |
wg.Done() |
Finally we need to tell the program where to block. The code after the call to wait() will not execute until all go routines have finished their tasks by them indicating so – by calling done()
1 |
wg.Wait() //Wait for the concurrent routines to call 'done' |
If you run this example, you will see that each call to the go routined function in main() get’s called and then moves on to the next goroutine call. Rather than sequentially calling goroutine A then goroutine B and goroutine C the function calls happen concurrently.
This is show by waiting in our goroutine for 3 seconds. Once the program executes it waits 3 seconds then all our called go routines will print their output together. If we didn’t use concurrency the program would wait 3 secs then print its first output, then wait another 3 seconds (6 seconds in total) and then print its output and finally wait again and finally finish after 9 seconds.
You might also notice that we can use call go routines on an anonymous function / closure. This is another of Go’s awesome features (first class functions).
1 2 3 4 5 |
go func(wg *sync.WaitGroup, val string) { time.Sleep(3 * time.Second) //Sleep a few secs fmt.Printf("Finished: %v - %v\n", val, time.Now()) wg.Done() }(&wg, "goroutine B") |
Note: This is not the only way to sync in Go. For a post on channels vs the above method please read – channels-vs-sync-package. I personally find the sync package cleaner
Conclusion
Go makes concurrency both clean and simple. Abstracting away all the complexities which other languages don’t. Because of this, there is no reason in this day and age you should not be writing concurrent code where you can
Hobby
thx for posting, really helpful.
tile kitchen backsplash Craftsbury Common VT
It is best to participate in a contest for probably the greatest blogs on the web. I’ll advocate this site!
Menno SD dog door
Very good blog! Do you have any recommendations for aspiring writers? I’m hoping to start my own site soon but I’m a little lost on everything. Would you recommend starting with a free platform like WordPress or go for a paid option? There are so many choices out there that I’m completely overwhelmed .. Any recommendations? Thanks!
colefax and fowler discount fabrics
Hi friends, how is all, and what you wish for to say on the topic of this
article, in my view its in fact awesome for me.
CollinJBudhu
Everyone loves it when individuals come together and share
opinions. Great website, continue the excellent work!
sandracn18
Very recently started supplementary occupation:
http://pat.w.telrock.org