Monitor class is one of the wait based synchronization primitive that provides gated access to the resource. It gates or throttles the access to the shared resource.
So,
Monitor assure that thread access the shared resource one thread at a time
Here is the code to use Monitor for shared resources to avoid the race condition
Here, sum++ is considered as the critical section, as this operation should be done in a thread-safe manner we use the monitor to carry out this operation as one thread at a time.
As you saw Monitor use Enter and Exit method which accepts an object to associate with lock primitive
Why?
locks are created by CLR only when you use monitor API to get acquisition of a lock (for performance reasons), so basically they are maintained as a table of the lock by CLR.
So,
When you pass this object in monitor method this object stores the index of the lock object created by CLR in their header as information to use this lock for gated access to the resource.
In short, this object is not the actual lock but stores reference to the lock object use by monitor class to access the resource in wait based manner.
Basically, you can use any type of object to associate with a lock. However, the recommended method is to use private objects and always avoid string as lock objects as the issue they cause due to their implementation method in CLR
Monitor Class Usage In C#
So Monitor has the same wait based technique usage. When you call the Monitor.Enter method you get the ownership of the lock, then you perform your thread-safe operation and then release the lock using Monitor.Exit.
Always remember this is the programmer understanding to use wait based technique thoughtfully at the required places as there are no physical restrictions on how you access the resource or implement the model. It’s just you deciding how to implement the flow of multithreading program and shared resources.
Exception Aware Monitor Usage
Now,
Consider the same example code above and there are two threads trying to acquire the lock X and Y now thread X got the ownership and Y got blocked until X releases the ownership.
However,
Before releasing the lock thread X threw some runtime exception error hence it will exit the code before releasing the lock, as a result, thread Y will get blocked forever.
We want to throw the exception but also want to release the lock.
So,
To overcome this problem we have to use proper try-finally construct to manage the exception (not handle it). Let’s see the code how to do it,
C# Lock Keyword
Some high level languages have syntactic sugar which reduces the amount of code that must be written in some common situation like above.
C# has this lock syntax for the same code we wrote above. Here is the code
so we simply use the lock keyword syntax and write critical section code in its body and compiler will generate the Exception Aware Monitor code for us. Sweet!
In the next post C# Task, we will learn more about Tasks in C#. Tasks provide a sophisticated way to handle async or parallel operation. Task object typically executes asynchronously on a thread pool thread.
Subscribe to Code with Shadman
Get the latest posts delivered right to your inbox