Protecting Shared Resource in Multithreading Using Locking

Protecting Shared Resource in Multithreading Using Locking

In this article, I am going to discuss How to Protect the Shared Resources in Multithreading using Locking from Concurrent Access with an example. Please read our previous article where we discussed the significance of the Alive and Join Method of Thread Class using some examples.

  1. What happened when accessing shared resources in a single-thread application?
  2. What happened when accessing shared resources in a multi-thread application?
  3. Understanding the Locking Mechanism.
  4. How to protect the shared resources in a multithread environment from concurrent access?

 

In a multithreading application, it is very important for us to handle multiple threads for executing critical section code. For example, if we have a shared resource and if multiple threads want to access the shared resource then we need to protect the shared resource from concurrent access otherwise we will get some inconsistence output. In C#, we can use lock and Monitor to provide thread safety in a multithreaded application. Both lock and monitor provides a mechanism which ensures that only one thread is executing the critical section code at any given point of time to avoid any functional breaking of code. In this article, I am going to discuss how to protect the shared resource using the lock and in the next article, I am going to discuss how to do the same thing using the monitor.

Accessing shared resource in a single-threaded environment:

Before understanding lock to protect the resource in a multithread environment, let us first understand the problem if we will not protect the shared resource. In the below example, we have a shared resource i.e. DisplayMessage() method and we call that method three times from the Main method as shown below.

using System.Threading;
using System;
namespace ThreadingDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            DisplayMessage();
            DisplayMessage();
            DisplayMessage();

            Console.Read();
        }

        static void DisplayMessage()
        {
            Console.Write("[Welcome to the ");
            Thread.Sleep(1000);
            Console.WriteLine("world of dotnet!]");
        }
    }
}

Output:

How to Protect the Shared Resources using Locking in Multithreading in C#

As the above program is a single-threaded program, so we got the output as expected. Let us see what happens if we access the shared resources in a multithreaded environment.

Accessing shared resource in a multithreaded environment:

In the following example, we created three different threads and then invoke the same DisplayMessage() method.

using System.Threading;
using System;
namespace ThreadingDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Thread t1 = new Thread(DisplayMessage);
            Thread t2 = new Thread(DisplayMessage);
            Thread t3 = new Thread(DisplayMessage);

            t1.Start();
            t2.Start();
            t3.Start();

            Console.Read();
        }

        static void DisplayMessage()
        {
            Console.Write("[Welcome to the ");
            Thread.Sleep(1000);
            Console.WriteLine("world of dotnet!]");
        }
    }
}

Output:

Concurrent access to Shared Resources in Multithreading using Locking

As you can see we are not getting the output as expected. So, the point that you need to keep in mind is, if the shared resources are not protected in the multithreaded environment from concurrent access then the output or the behavior of the application becomes inconsistent that’s what we see in our previous example.

How to protect the shared resources in a multithread environment from concurrent access in C#?

We can protect the shared resources in a multithread environment from concurrent access by using the concept Monitor and locking. Let us see how to protect the shared resource using locking and see the output.

using System.Threading;
using System;
namespace ThreadingDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Thread t1 = new Thread(DisplayMessage);
            Thread t2 = new Thread(DisplayMessage);
            Thread t3 = new Thread(DisplayMessage);

            t1.Start();
            t2.Start();
            t3.Start();

            Console.Read();
        }

        private static object _lockObject = new object();
        static void DisplayMessage()
        {
            lock(_lockObject)
            {
                Console.Write("[Welcome to the ");
                Thread.Sleep(1000);
                Console.WriteLine("world of dotnet!]");
            }
        }
    }
}

Now run the application and see the output as expected as shown below.

Protecting Shared Resource in Multithreading Using Locking

Note: The section or block or particular resource that you want to protect should be placed inside the lock block.

Let us understand this with an example. In the following example, we are only protecting the shared Count variable from concurrent access.

using System.Threading;
using System;
namespace ThreadingDemo
{
    class Program
    {
        static int Count = 0;

        static void Main(string[] args)
        {
            Thread t1 = new Thread(IncrementCount);
            Thread t2 = new Thread(IncrementCount);
            Thread t3 = new Thread(IncrementCount);

            t1.Start();
            t2.Start();
            t3.Start();

            //Wait for all three threads to complete their execution
            t1.Join();
            t2.Join();
            t3.Join();

            Console.WriteLine(Count);
            Console.Read();
        }

        private static object _lockObject = new object();
        static void IncrementCount()
        {
            for (int i = 1; i <= 1000000; i++)
            {
                //Only protecting the shared Count variable
                lock (_lockObject)
                {
                    Count++;
                }
            }
        }
    }
}

When you run the above program, it will give you the output as expected as 3000000. Here, in this article, I try to explain How to Protect the Shared Resources in Multithreading using Locking from concurrent access. In the next article, I am going to discuss how to protect the shared resources in a multithread environment using Monitor with examples.

Leave a Reply

Your email address will not be published. Required fields are marked *