InterLocked Access of Memory to Avoid Race Condition

Multi-threading is not new to the programming world. We use multi-threading in our applications to enhance the throughput and responsiveness of the application, but with concurrent access of certain resources, the application is prone to deadlocks and race conditions. This article will explain how to avoid such scenarios.

What is a deadlock?

When two or more threads are trying to lock a resource that are already exclusively locked by some other thread, a deadlock can occur. In this case the two threads continue to wait but no one gets the exclusive lock on the resource.

To solve the problem you can use "Monitor.TryEnter" to specify the timeout seed value that will ensure that the thread will not wait infinitely rather will wait until the timeout is reached, or you can use a shared lock using the ReaderWriterLock class.

What a Race Condition is

A Race Condition is a situation in which two or more threads attempt to access a resource at the same time leaving the program in an inconsistent state.

Say for instance:

  1. Thread 1 checks the value of X being 1;  
  2. Thread 2 checks the value of X being 1;  
  3. Thread 1 tries to increment the value of X to 2; Invokes x = x + 1; // 2  
  4. Thread 2 tries to increment the value of X to 2; invokes x = x + 1 // 3 (inconsistent)  

Thus thread 2 is in inconsistent state since it tries to increment the value of X to 2 while it gets 3.

A race condition can be avoided using a class called Interlocked. The class Interlocked exposes a number of methods that allows ThreadSafe access to a value and ensures that an inconsistent thread does not appear in the program. In this case, it will ensure that the value of X is 1 for every thread when it increments the value otherwise loaded again.

To increment/decrement a value of a variable:

  1. Interlocked.Increment(ref x); //increments the value by 1  
  2. Interlocked.Decrement(ref x); //decrements the value by 1  
  3. Interlocked.Add(ref x, 10); //adds value 10 to x  

 Comparing the Loaded Value

  1. Interlocked.CompareExchange(ref x, y, 10);  

The code ensures the value of x is 10 when the comparison occurs with y. Hence if no other thread is updating the value of X, the value of X will be equal to 10 during the comparison.

I hope this article helped you.

Thanks for reading.