C# Interlocked

Summary: in this tutorial, you’ll learn how to use the C# InterLocked class to perform atomic operations on shared variables.

Introduction to the C# Interlocked class

The Interlocked class provides a set of methods that allow you to perform atomic operations on shared variables.

For example, if multiple threads modify a shared variable concurrently, the final value of the variable may be unpredictable or incorrect.

The reason is that incrementing a variable is not an atomic operation because the program needs to perform three steps:

  • First, read the current value of the shared variable.
  • Second, increase the value.
  • Third, write the new value back to the shared variable.

If thread one is increasing the value but not yet writing the new value to the shared variable (at step 2), thread two may read the original value and increase it. As the result, the update from thread one may be lost.

To solve this synchronization issue, you can use the Increment() method of the Interlocked class to increase the shared variable atomically.

Unlike regular increments, the Interlocked.Increament() method increments the shared variable atomically, ensuring that the operation is completed before another thread can access the variable.

The following program demonstrates how to use the InterLock class to perform atomic increments of a shared variable counter across two threads:

int counter = 0;

void Increase()
{
    for (int i = 0; i < 1000000; i++)
    {
        Interlocked.Increment(ref counter);

    }
    Console.WriteLine("The counter is " + counter);
}

Task.Run(() => Increase());
Task.Run(() => Increase());

Console.ReadLine();Code language: C# (cs)

Output:

The counter is 1942623
The counter is 2000000Code language: C# (cs)

If you wonder why the output has a random number like 1942623, please check out the lock tutorial for a detailed explanation.

How it works.

First, declare an integer variable counter and initialize its value to zero.

int counter = 0;Code language: C# (cs)

Second, define Increase() function that increments the counter using the Increment() method of the Interlocked class in a loop and displays the counter value to the console:

void Increase()
{
    for (int i = 0; i < 1000000; i++)
    {
        Interlocked.Increment(ref counter);

    }
    Console.WriteLine("The counter is " + counter);
}Code language: C# (cs)

Third, create two tasks that execute the Increase() method in separate threads. Both tasks (or threads) will increment the counter variable concurrently:

Task.Run(() => Increase());
Task.Run(() => Increase());Code language: C# (cs)

Finally, use the Console.ReadLine() to pause the program and allow enough time for the two tasks to complete before you hit the enter (or return key):

Console.ReadLine();Code language: C# (cs)

Interlocked vs. lock

Both Interlocked and lock allow thread synchronization and prevent race conditions when multiple threads attempt to access the same shared variable concurrently. But they have some differences:

  • Interlocked only provides atomic operations such as Increment, Decrement, Exchange, etc. These methods are useful when you need to perform on a shared variable.
  • The lock statement provides mutual exclusion that allows only one thread can execute a critical block of code at a time.

The lock can execute a block of code atomically while the Interlocked can perform limited operations on a shared variable atomically. In other words, the Interlocked is more lightweight than the lock.

Summary

  • Use the Interlocked class to perform atomic operations on shared variables.
Was this tutorial helpful ?