Threading Simplified: Part 9 (Thread Locking)

This article explains what Thread Locking is and how to use it efficiently in multithreading environment. 

Before reading this article, I highly recommend reading my previous parts:

Thread Locking, lock keyword

I am again here to continue the discussion around Threading. Today, we will discuss about Thread Locking and related concepts.

Let’s start by putting questions to understand the concepts.

Why Thread Locking?

Locking is used to ensure that only one thread can enter at a time in a code block.

Is Locking Thread Safe by default?

Locking is not thread safe by default and one needs to handle it explicitly to avoid thread clash in a multithreaded environment.

Good so far. Let’s understand it bya simple example.

  1. class TestThreadSafe  
  2. {  
  3.     int num1 = 0;  
  4.     int num2 = 0;  
  5.     Random rnd = new Random();  
  6.     public void DoDivide()  
  7.     {  
  8.         for(inti = 0; i < 1000000; i++)  
  9.         {  
  10.             num1 = rnd.Next(1, 5);  
  11.             num2 = rnd.Next(1, 5);  
  12.             Console.WriteLine(num1 / num2);  
  13.             num1 = 0;  
  14.             num2 = 0;  
  15.         }  
  16.     }  
  17. }  
  18. class Program  
  19. {  
  20.     static void Main(string[] args)  
  21.     {  
  22.         Console.Title = "Thread Locking Demo";  
  23.         TestThreadSafe testThreadSafe = new TestThreadSafe();  
  24.         Threadt1 = new Thread(testThreadSafe.DoDivide);  
  25.         Threadt2 = new Thread(testThreadSafe.DoDivide);  
  26.         t1.Start();  
  27.         t2.Start();  
  28.     }  
  29. }  
Output:

error

Hope you realized the problem what’s going wrong here. In case you are still thinking it's not a problem,  it’s a one of the concurrency issue that may occur in multithread environment.

If you see the code closely, you can see that at any given instance, thread1 (or t1) may be at LN3 and thread2 (or t2) may be executing LN5. In that case compiler may throw DivideByZeroException.
  1. num1 = rnd.Next(1, 5); //LN1  
  2. num2 = rnd.Next(1, 5); //LN2  
  3. Console.WriteLine(num1 / num2); //LN3 thread1  
  4. num1 = 0; //LN4  
  5. num2 = 0;//thread2 //LN5 thread5  
So, we understand the problem now, so what’s the solution?

Well,the solution is to handle the concurrency properly. Here we can use lock keyword to address the problem.

Let’s fix the issue by adding a variable and modifying the Do Divide method a  little bit as in the following.
  1. class TestThreadSafe  
  2. {  
  3.     private static objectmyLock = newobject();  
  4.     public void DoDivide()  
  5.     {  
  6.         lock(myLock) //This will ensure that only one thread can enter into code.  
  7.         {  
  8.             for(inti = 0; i < 1000000; i++)  
  9.             {  
  10.                 num1 = rnd.Next(1, 5);  
  11.                 num2 = rnd.Next(1, 5);  
  12.                 Console.WriteLine(num1 / num2);  
  13.                 num1 = 0;  
  14.                 num2 = 0;  
  15.             }
  16.         }  
  17.     }  
  18. }
Output:

run

As you can see that exception (DivideByZeroException) which we got in the previous example is not happening anymore as we have enclosed the problematic code within the lock keyword which ensures that only one thread can enter into it.

Note: I have seen some people use as lock(this) that locks the complete class instance which at times may lead to a deadlock situation. So the recommended practice is to have a private static variable created in a class and lock that variable only.

Hope you have liked the article. Look forward for your comments/suggestions.

Read more articles on Multithreading:

 

X

Build smarter apps with Machine Learning, Bots, Cognitive Services - Start free.

Start Learning Now