Access Critical Regions Carefully — Practical Approach in Golang
What is the critical region/section and why do we need that?
In simple, a piece of information needs to executed atomically is called a critical region or a critical section. So in concurrent programming behavior, some concurrent access to information might be erroneous behavior so those shared resources need to be shared their state atomically. Like single thread can access a single resource at a single time. Resources might be like shared memory, shared files, shared port, etc…
Common errors while accessing the critical region
I have simply done code with a single increment function which having increment the global variable. That global variable is incrementing from 0 to 10.
So in the above code value of the global variable should be 10 at the last. But this code behaves some unexpected behavior. (Output may vary every time when you’ll execute code. As the goroutines scheduling might be done the trick.)
So what is good practices to access critical region?
Golang provides “sync” package to handle such situations. As sync package contains
- Mutex
- Syncmaps
Here we talk about the mutex only(the sync maps also do the same tricks)
Mutex
Mutex is also known as Mutual exclusion. This ensures that no goroutines access the same resource at a time(Single goroutine access a single resource at a time). Using a mutex programmer ensures the only process accessing a region.
Mutex ensures the atomic behaviour of the of code .
Go’s standard library provides mutual exclusion with sync.Mutex
and its two methods:
Lock
Unlock
Sequential Processes
The above example ensures that the only goroutine accessing the variable named global.
There are types of locks also available like
- Read lock
- Write lock
- Read-Write lock etc.
If we compare code with the first image called Simple Critical Section Cycle, We see that
- We keep waiting for the other goroutines to execute a current code as we add the lock over the process
- Executing a current thread as we adding 1 in a global variable
- And after work done we release a critical section by adding an unlock method
The real-world examples:
- As many systems are getting generated the user IDs through the systems so those locks can be useful to not provide the same user IDs to multiple users. Multiple HTTP requests getting hit to the server at the same time and all the requests should get processed through and unique user IDs generated.
- The operating system is also using the mutex variable to implement the threads.
- The banking transactions is also an example of the mutex.
Critical regions are like global variables in code they can access anywhere and everywhere but while changing their value might affect atomic threads.
Hope you’ve enjoyed the reading :)