Click here to Skip to main content
15,886,362 members
Articles / Programming Languages / C#
Tip/Trick

Monitor and Lock in C#

Rate me:
Please Sign up or sign in to vote.
4.69/5 (11 votes)
23 Jun 2014CPOL3 min read 85.8K   3   20   6
Monitor and lock in C#

Introduction

When working with a multithreading application, it is very important for developers to handle multiple threads for a critical section of code.

Monitor and lock is the way to provide thread safety in a multithreaded application in C#. Both provide a mechanism to ensure that only one thread is executing code at the same time to avoid any functional breaking of code.

Lock

Lock is the keyword in C# that will ensure one thread is executing a piece of code at one time. The lock keyword ensures that one thread does not enter a critical section of code while another thread is in that critical section.

Lock is a keyword shortcut for acquiring a lock for the piece of code for only one thread.

Sample Code

C#
1.    namespace Monitor_Lock   
2.    {   
3.        class Program   
4.        {   
5.            static readonly object _object = new object();   
6.       
7.            static void TestLock()   
8.            {   
9.                   
10.                lock (_object)   
11.                {   
12.                    Thread.Sleep(100);   
13.                    Console.WriteLine(Environment.TickCount);   
14.                }   
15.            }   
16.       
17.            static void Main(string[] args)       
18.            {   
19.                for (int i = 0; i < 10; i++)   
20.                {   
21.                    ThreadStart start = new ThreadStart(TestLock);   
22.                    new Thread(start).Start();   
23.                }   
24.       
25.                Console.ReadLine();   
26.            }   
27.        }   
28.    } 

Output

Here we see a static method "TestLock" that uses the lock statement on an object. When the method TestLock is called many times on new threads, each invocation of the method accesses the threading primitives implemented by the lock.

The Main method creates ten new threads and then calls Start on each one. The method TestLock is invoked ten times, but the tick count shows the protected method region is executed sequentially, about 100 milliseconds apart.

If another thread tries to enter a locked code, it will wait, block, until the object is released.

The lock keyword marks a statement block as a critical section by obtaining the mutual-exclusion lock for a given object, executing a statement and then releasing the lock.

Monitor

Monitor provides a mechanism that synchronizes access to objects. It can be done by acquiring a significant lock so that only one thread can enter in a given piece of code at one time. Monitor is no different from lock but the monitor class provides more control over the synchronization of various threads trying to access the same lock of code.

Using a monitor, it can be ensured that no other thread is allowed to access a section of application code being executed by the lock owner, unless the other thread is executing the code using a different locked object.

The Monitor class has the following methods for the synchronize access to a region of code by taking and releasing a lock:

  • Monitor.Enter
  • Monitor.TryEnter
  • Monitor.Exit

Monitor locks objects (that is, reference types), not value types. While you can pass a value type to Enter and Exit, it is boxed separately for each call.

Wait releases the lock if it is held and waits to be notified. When Wait is notified, it returns and obtains the lock again. Both a Pulse and PulseAll signal for the next thread in the wait queue to proceed.

The following is the syntax for using a monitor.

C#
1.    try   
2.    {   
3.        int x = 1;   
4.           
5.       Monitor.Enter(x);   
6.        try   
7.        {   
8.            // Code that needs to be protected by the monitor.   
9.        }   
10.        finally   
11.        {   
12.               
13.           Monitor.Exit(x);   
14.        }   
15.    }   
16.    catch (SynchronizationLockException SyncEx)   
17.    {   
18.        Console.WriteLine("A SynchronizationLockException occurred. Message:");   
19.        Console.WriteLine(SyncEx.Message);   
20.    }  

Sample Code

C#
1.    namespace Monitor_Lock   
2.    {   
3.        class Program   
4.        {   
5.            static readonly object _object = new object();   
6.       
7.            public static void PrintNumbers()   
8.            {   
9.                Monitor.Enter(_object);   
10.                try   
11.                {   
12.                    for (int i = 0; i < 5; i++)   
13.                    {   
14.                        Thread.Sleep(100);   
15.                        Console.Write(i + ",");   
16.                    }   
17.                    Console.WriteLine();   
18.                }   
19.                finally   
20.                {   
21.                    Monitor.Exit(_object);   
22.                }   
23.            }   
24.       
25.            static void TestLock()   
26.            {   
27.                   
28.                lock (_object)   
29.                {   
30.                    Thread.Sleep(100);   
31.                    Console.WriteLine(Environment.TickCount);   
32.                }   
33.            }   
34.       
35.            static void Main(string[] args)       
36.            {   
37.       
38.                   
39.                Thread[] Threads = new Thread[3];   
40.                for (int i = 0; i < 3; i++)   
41.                {   
42.                    Threads[i] = new Thread(new ThreadStart(PrintNumbers));   
43.                    Threads[i].Name = "Child " + i;   
44.                }   
45.                foreach (Thread t in Threads)   
46.                    t.Start();   
47.       
48.                Console.ReadLine();   
49.            }   
50.        }   
51.    } 

Output

In C# 4.0 , overloaded function for Monitor.Enter(_object,ref _lockTaken).

That acquires an exclusive lock and the specified object and automatically sets a value that indicates whether the lock was taken.

C#
1.    class Program   
2.    {   
3.         static readonly object _object = new object();   
4.       
5.         public static void PrintNumbers()   
6.         {   
7.             Boolean _lockTaken = false;   
8.       
9.             Monitor.Enter(_object,ref _lockTaken);   
10.             try   
11.             {   
12.                for (int i = 0; i < 5; i++)   
13.                {   
14.                   Thread.Sleep(100);   
15.                   Console.Write(i + ",");   
16.                }   
17.                Console.WriteLine();   
18.             }   
19.             finally   
20.             {   
21.                if (_lockTaken)   
22.                {   
23.                   Monitor.Exit(_object);   
24.                }   
25.             }  
     } 
26.    }  

Important Sticky

The Monitor class is a static class and its instance cannot be created.

The Monitor class object uses the Monitor.Enter, Monitor.TryEnter, and Monitor.Exit methods. Once you have a lock on a code region, you can use the Monitor.Wait, Monitor.Pulse, and Monitor.PulseAll methods.

It is associated with an object on demand.

It is unbound, which means it can be called directly from any context.

Conclusion

Lock and monitor are basically used for the same purpose in multithreading, the difference is that only when we want more control over synchronization with multiple threads running for a specific section of code.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
BugExpect Race-Conditions Pin
Tekahe24-Mar-17 21:30
Tekahe24-Mar-17 21:30 
GeneralMy vote of 5 Pin
Lydia Gabriella16-Jul-14 10:53
Lydia Gabriella16-Jul-14 10:53 
GeneralRe: My vote of 5 Pin
Abhishek Geek17-Jul-14 0:15
professionalAbhishek Geek17-Jul-14 0:15 
GeneralMy vote of 1 Pin
Eartufts30-Jun-14 21:17
Eartufts30-Jun-14 21:17 
GeneralRe: My vote of 1 Pin
Abhishek Geek1-Jul-14 19:41
professionalAbhishek Geek1-Jul-14 19:41 
QuestionCopied & Re-Written Article from DotNetPerls? Pin
Eartufts24-Jun-14 4:02
Eartufts24-Jun-14 4:02 
Looks like a copy & rewrite of http://www.dotnetperls.com/lock[^] to me.

Coincidence, or did you forget to name some sources?

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.