Concurrency with Go Lang
Before moving into discussion on concurrency in context of go language, we need to get a simple idea about concurrency. As a software developer, you might be very confident in this scope, but for the consistency of the article, I will briefly describe about the concurrency as well.
So, Heads up! What is concurrency?
Simply, concurrency is ability to manage various tasks at once. But does that mean that you need to do multiple tasks at the same time to achieve the concurrency? That is very wrong and that is one of the biggest misunderstanding among developers. So, what is the real idea of concurrency?
To get a clear idea about concurrency, we need to have an understanding on both concepts called Parallelism and concurrency.
So, Parallelism is doing multiple tasks parallelly. It means that system is performing multiple process without pausing one to perform another. At a given point of time, all those processes are performing their tasks.
But in context of concurrency, processor runs a single task at once, but it does context switching between the other tasks waiting to be performed and complete them step by step. For an example, when you watch a video online, browser download a chunk of the video and then renders it to user and then again download another chunk. Likewise, it performs downloading and rendering concurrently.
Concurrency
Achieve Concurrency with GO
The concept “GOROUTINES” is the feature which is introduced to Go language to achieve concurrency. Simply, Goroutine is a lightweight execution thread. Go application can have thousands or millions of Goroutines. So, to introduce the concept of Goroutine, there should be an advantage of Goroutines over threads.
Goroutine is lightweight and cheap when compared to a thread. It requires less memory and easy to manage as well. All of these Goroutines are managed by Go runtime.
Go go
To get a new Goroutine which runs concurrently, we use the keyword “go”.
So, we are going to understand, how a Goroutine works.
Here, I have written a simple Go Language module which include a function to return a Hello message. You can learn about Go modules by referring documentation of Go language.
Here, we can see that we input a name to this function, and it returns a greeting message. This is the example used in Go language documentation to explain the Go modules. I used it to explain Goroutine. Then we use this module in our main program. We call Hello function in greetings module. We have declared the greetings module in go.mod file.
So, the implementation is complete and now we build the program using go build command. Then we get an executable version of our program “hello.exe” and we run it using command prompt. Output is below.
As we can see, it only prints the 22nd line in our main program. (Check the image) But we can not see the print statement of Goroutine we have declared in line 21. What is the reason for this?
Here, the main program runs in one Goroutine and the Goroutine we declared runs separately. But main Goroutine should be in running condition for the other Goroutines to run. After the Goroutine we declared in the main Goroutine, started running, Control returns to the next line of the main Goroutine. So, after executing the print statement in main Goroutine, program terminated because it has come to an end. It did not wait for the Goroutine hello function execution.
To avoid this, below example we have added a Sleep method using time package and it sleeps the main Goroutine for a second. Meantime, Goroutine with print statement in line 21 can complete its execution.
Now we can get the expected output.
So, in our next example, I implemented two functions which prints a statement and I added multiple Goroutines to our main program.
What is the reason for this confusion?
With the modification to our main program, it invokes three Goroutines in Line 32,33 and 34. They start execution concurrently. We give them time to complete execution by sleeping the Main Goroutine to 3 seconds. Since Go runtime allocating and executing three routines concurrently, Output to the console is varying each time.
We can get an expected output by sleeping each function after each round of loop by adding a sleep inside the loop. Try it as a homework.
Adding Parallel Processing to the Application
Simply adding this line of code to our main function, we can command our application to run in multiple cores (Here we have allowed to use four cores) to achieve parallelism. This speeds up the execution. So, these Goroutines can run separately on multiple cores and it increases the performance of the execution.
Wrapping up the article, we are going to discuss about Channels in Go Language. Channel is the feature which is used in Goroutines to communicate with each other to synchronize the execution. We will be taking a deep dive into Go Lang channels next.
Mithun Wijethunga,
Intern: Software Engineering