Introduction
To coordinate threads interaction when accessing a shared resource some kind of synchronization mechanism is required. .NET offers many synchronization primitives that user can utilise according to a particular need.
In this post I present one of the synchronization primitives – Interlocked class.
This is a first post of the synchronization primitives series. I plan to add more posts to describe other primitives that .NET offers (e.g. Mutex, SemaphoreSlim, Barrier etc.).
Interlocked class
The Interlocked class is a static class that provides atomic operations for variables that are shared by multiple threads (as per docs). Let’s focus on a simple incrementation operation and the following example:
- we have a global variable named
counter
, - we run many threads at the same time that increment the
counter
value.
At first everything looks fine as incrementing the counter
looks like something that cannot be messed up in terms of accessing by many threads – but it is not true. As you can read in the docs – on most computers incrementing is not an atomic operation and consists of three steps:
- load a
counter
value into a register, - increment the value,
- store a value in the
counter
variable.
As you can see instead of one (apparently) one atomic operation there are tree steps that happen behind the scene. Thread can be preempted after executing the first two steps, then another thread executes all three steps and at the end first thread finishes the last step. In this case instead of having the counter + 2
result the result is counter + 1
:
Example
Let’s consider the source code from my GitHub. As you can see the StandardIncrement
method increments passed argument using ++
operator whereas the InterlockedIncrement
method uses the Interlocked.Increment
. If you run the provided code using dotnet run -c Release
command you might see a similar output:
StandardIncrement: 9985
InterlockedIncrement: 10000
Behind the scene
Let’s see what are the ASM instructions for the source code. For this purpose we will use sharplab – interesting part of the output is highlighted:
What we can see is that these two methods (while doing the same) are represented by slightly different instructions. The InterlockedIncrement
method uses the LOCK prefix which makes the instruction atomic whereas the StandardIncrement
does not (interesting explanation in the link).
Summary
In this post I presented and explained the Interlocked
synchronization primitive in the .NET environment. The API of theInterlocked
class consists of many methods and I encourage you to give it a try on your own. As always you can find source code on my GitHub repository.
Have a nice day, bye!
Be First to Comment