Protecting Shared Resource in Multithreading Using Monitor

Protecting Shared Resource in Multithreading Using Monitor

In this article, I am going to discuss How to Protect the Shared Resources in Multithreading using Monitor from Concurrent Access with some examples. Please read our previous article before proceeding to this article where we discussed why we need to protect the shared resource as well as how to protect the shared resource using the lock with some examples.

As we already discussed both Monitor and lock are used to provide thread safety to a shared resource in a multithreaded application in C#. So, let us understand the Monitor class and its methods in details as well as how to protect the shared resource using the monitor class.

Monitor Class in C#:

The Monitor class in C# provides a mechanism that synchronizes access to objects. Let us simplify the above definition. In simple word, we can say that, like the lock, we can also use this class to protect the shared resources in a multi-threaded environment. This can be done by acquiring an exclusive lock on the object so that only one thread can enter into the critical section at any given point of time.

The Monitor is a static class and belongs to the System.Threading namespace. As a static class, it provides a collection of static methods as shown in the below image. Using these static methods you can provide access to the monitor associated with a particular object.

Monitor Class in C#

Let us understand the methods of the Monitor class.

Enter, TryEnter:

These two methods are used to acquire an exclusive lock for an object. This action marks the beginning of a critical section. No other thread can enter into the critical section unless it is executing the instructions in the critical section using a different locked object.

Wait:

The Wait method is used to release the lock on an object and permit other threads to lock and access the object by blocking the current thread until it reacquires the lock. The calling thread waits while another thread accesses the object. Pulse signals are used to notify waiting threads about changes to an object’s state.

Pulse (signal), PulseAll:

The above two methods are used to send a signal to one or more waiting threads. The signal notifies a waiting thread that the state of the locked object has changed, and the owner of the lock is ready to release the lock.

Exit():

The Exit method is used to release the exclusive lock from the specified object. This action marks the end of a critical section protected by the locked object.

Example:

Let us see an example to understand how to use Monitor in C#.

using System;
using System.Threading;

namespace MonitorDemo
{
    class Program
    {
        static readonly object lockObject = new object();

        public static void PrintNumbers()
        {
            Console.WriteLine(Thread.CurrentThread.Name + " Trying to enter into the critical section");
            Monitor.Enter(lockObject);
            try
            {
                Console.WriteLine(Thread.CurrentThread.Name + " Entered into the critical section");
                for (int i = 0; i < 5; i++)
                {
                    Thread.Sleep(100);
                    Console.Write(i + ",");
                }
                Console.WriteLine();
            }
            finally
            {
                Monitor.Exit(lockObject);
                Console.WriteLine(Thread.CurrentThread.Name + " Exit from critical section");
            }
        }

        static void Main(string[] args)
        {
            Thread[] Threads = new Thread[3];
            for (int i = 0; i < 3; i++)
            {
                Threads[i] = new Thread(PrintNumbers);
                Threads[i].Name = "Child Thread " + i;
            }

            foreach (Thread t in Threads)
            {
                t.Start();
            }

            Console.ReadLine();
        }
    }
}

Output:

How to Protect the Shared Resources in Multithreading using Monitor from Concurrent Access
Monitor.EnterlockObject, ref IslockTaken):

Let us understand the overloaded version of the Enter method. The Monitor.Enter(lockObject, ref IslockTaken) acquires an exclusive lock on the specified object. It then automatically sets a value that indicates whether the lock was taken or not. The second parameter which is a Boolean parameter returns true if the lock is acquired else it returns false.

Example:

using System;
using System.Threading;

namespace MonitorDemo
{
    class Program
    {
        static readonly object lockObject = new object();

        public static void PrintNumbers()
        {
            Console.WriteLine(Thread.CurrentThread.Name + " Trying to enter into the critical section");
            Boolean IsLockTaken = false;

            Monitor.Enter(lockObject, ref IsLockTaken);
            try
            {
                Console.WriteLine(Thread.CurrentThread.Name + " Entered into the critical section");
                for (int i = 0; i < 5; i++)
                {
                    Thread.Sleep(100);
                    Console.Write(i + ",");
                }
                Console.WriteLine();
            }
            finally
            {
                Monitor.Exit(lockObject);
                Console.WriteLine(Thread.CurrentThread.Name + " Exit from critical section");
            }
        }

        static void Main(string[] args)
        {
            Thread[] Threads = new Thread[3];
            for (int i = 0; i < 3; i++)
            {
                Threads[i] = new Thread(PrintNumbers);
                Threads[i].Name = "Child Thread " + i;
            }

            foreach (Thread t in Threads)
            {
                t.Start();
            }

            Console.ReadLine();
        }
    }
}

Output:

How to Protect the Shared Resources in Multithreading using Monitor from Concurrent Access

Difference between Monitor and lock in C#

The lock is the shortcut for Monitor.Enter with try and finally. So, the lock provides the basic functionality to acquire an exclusive lock on a synchronized object. But, If you want more control to implement advanced multithreading solutions using TryEnter() Wait(), Pulse(), & PulseAll() methods, then the Monitor class is your option.

Here, in this article, I try to explain How to Protect the Shared Resources in Multithreading using Monitor class from concurrent access. In the next article, I am going to discuss the Mutex in C# with some examples. I hope you understood the need and how to use the Monitor class in C#.

Leave a Reply

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