GoRoutines are one of the most unique and most used features of Golang. Goroutines are used to process concurrent tasks. A goroutine is simply a lightweight execution thread and a function that executes concurrently with the rest of the program. The cost of creating a Goroutine is tiny when compared to a thread.
Before we dive deep into the GoRoutines let's first understand the meaning of Concurrency.
Concurrency and Parallelism
Concurrency is when two or more tasks can start, run, and complete in overlapping time periods. It doesn't necessarily mean they'll ever both be running at the same instant. Concurrency is a semantic property of a program or system. Concurrency is when multiple tasks are in progress for overlapping periods of time.
Parallelism is about multiple tasks or subtasks of the same task that literally run at the same time on hardware with multiple computing resources like a multi-core processors. Parallelism is an implementation property. Parallelism is literally the simultaneous physical execution of tasks at runtime, and it requires hardware with multiple computing resources. It resides on the hardware layer.
For Example - if you are listening to music and reading at the same time then it is parallelism because you are doing two tasks at the same time. If you are listening to music and for a moment you paused the music and start reading, then you again start the music and pause the reading, that is concurrency. Here the two tasks were done together but not at the same time, hence concurrent.
What are GoRoutines?
A goroutine is a lightweight thread managed by the Go runtime. We, use goroutines to create concurrent programs. Concurrent programs are able to run multiple processes at the same time. Giving us the power to simultaneously process information while saving time. Goroutines are lightweight abstractions over threads because their creation and destruction are very cheap as compared to threads, and they are scheduled over OS threads. To create you just have to start the file with `go` word, here is an example
package main
import (
"fmt"
)
func hello() {
fmt.Println("Hello world goroutine")
}
func main() {
go hello() // a go routine
fmt.Println("main function")
}
go hello()
starts a new Goroutine. Now the hello()
function will run concurrently along with the main()
function. The main function runs in its own Goroutine and it's called the main Goroutine.
To understand its working we have to keep a few things in mind. When a new Go routine is created it will run inside a parent Go routine which is the file that is executing the code. If the code inside the file ends or the parent thread is finished executing then it will also terminate the child routine. hence only main function
is printed and the hello()
routine is terminated along with the parent in the next line. The main Goroutine should be running for any other goroutine to run. If the main Goroutine terminates then the program will be terminated and no other Goroutine will run**.** That's the secret sauce.
Think yourself how to fix we need some delay so that the hello()
routine is done executing and then we jump to the next line. For that what do we need? A simple delay that's it!!
package main
import (
"fmt"
"time"
)
func hello() {
fmt.Println("Hello world goroutine")
}
func main() {
go hello()
time.Sleep(1 * time.Second) // here is the delay
fmt.Println("main function")
}
This will wait for 1 sec
, in that time the go routine can execute itself. Now the call to go hello()
has enough time to execute before the main Goroutine terminates. This program first prints Hello world goroutine
, After 1 sec we start reading from the next line. In the same fashion, we can create multiple Go routines as per our needs.
What makes them different from threads?
Channels: Goroutines have an easy communication medium known as channels. Due to the presence of channel one, the goroutine can communicate with other goroutines with low latency. Thread does not have an easy communication medium. Due to the lack of easy communication medium inter-thread communicate takes place with high latency.
Setup and Teardown cost: Threads have significant setups and teardown costs because it has to request resources from the OS and return it once it’s done. While Goroutines are created and destroyed by the go runtime (it manages scheduling, garbage collection, and the runtime environment for Goroutines) and those operations are pretty cheap.
Switch cost: This difference is mainly because of the difference in the scheduling of Goroutines and threads. Threads are scheduled preemptively (If a process is running for more than a scheduler time slice, it would preempt the process and schedule execution of another runnable process on the same CPU), the schedular needs to save/restore all registers
How are Go routines Executed?
There are three entities Go uses to explain the Goroutine scheduling.
Processor (P)
OSThread (M)
Goroutines (G)
Go works on a type of scheduler called an m:n scheduler (M:N scheduler), which states that M number of goroutines can be distributed over N number of OS threads. Comparatively, OS threads have much more overhead than goroutines. Therefore, Go uses a limited number of threads to run a maximum number of goroutines.
Go scheduler distribute runnable goroutines over multiple worker OS threads that runs on one or more processors. Every P has a local Goroutine queue. There’s also a global Goroutine queue which contains runnable Goroutines. Each M should be assigned to a P. Ps may have no Ms if they are blocked or in a system call.
At any time, there are at most GOMAXPROCS number of P and only one M can run per P. More Ms can be created by the scheduler if required. In each round of scheduling, scheduler finds a runnable G and executes it. Once a runnable G is found, it gets executed until it is blocked.
If you made it this far don't forget to drop by and leave a comment!!
References
https://riteeksrivastava.medium.com/a-complete-journey-with-goroutines-8472630c7f5c
https://riteeksrivastava.medium.com/a-complete-journey-with-goroutines-8472630c7f5c
https://riteeksrivastava.medium.com/a-complete-journey-with-goroutines-8472630c7f5c