Using ReaderWriterLock over Monitor for Thread Locking

If you are looking for Multi-Threaded application, you must have already tried our very old lock statement (synclock in VB.NET). The lock statement is the most common practice to make certain block of code Thread safe or in other words, it blocks all other Thread from entering the block which one thread is actually executing. The lock statement is actually producing Monitor.Enter in try and Monitor.Exit in finally. Hence it exclusively locks the block for you.

Limitation of Monitor

Now what is the limitation of lock statement? The first is that it locks the whole object and does not give you a chance to provide a Timeout seed. Hence it might produce deadlock situation in certain scenarios, but you can easily handle this using Monitor.TryEnter instead of Enter which lets you specify a timeout.

But the second and most important limitation of Monitor is that it always provide you an exclusive locking. Thus if a certain resource is read and written by multiple Threads at a time exclusive locking might produce inefficiencies. It is similar to what we see in Databases. Reads are generally cannot be inconsistent when multiple threads are reading it simultaneously only if some thread updates it. Hence exclusive locking is inefficient in case of reading a resource.

ReaderWriterLock allows shared locks together with exclusive locks. Hence it is possible to read the same resource using sharedlocking, each time the Readerlock is invoked the Lock count is increased but allows you to read the block of code inside it. ReaderWriterLock also give you an option for exclusive locking using WriteLock statement to eliminate inconsistent reads. Lets see how to use this with code.

static ReaderWriterLock locker = new ReaderWriterLock();
public static List Repository = new List();

public static long Sum()
{

locker.AcquireReaderLock(1000);

long counter = 0;
try
{
for (int i = 0; i < Repository.Count; i++) Interlocked.Add(ref counter, Repository[i]); } finally { locker.ReleaseReaderLock(); } return counter; } public static void AddToRepository(int nos) { if (locker.IsWriterLockHeld) return; locker.AcquireWriterLock(1000); try { for (int i = 0; i < nos; i++) Repository.Add(i); } catch { } locker.ReleaseWriterLock(); }[/code] The AddToRepository is only used to add some integer values to a List. You can easily lock the Repository using lock(Repository) statement, and that will mean an exclusive locking will be established. On the other hand, the code written inside AddToRepository also produces exclusive locking using AquireWriterLock statement. You can optionally specify the timeout value for the WriterLock. (specify TimeSman.Infinite when you don’t need timeout).
But on the method Sum which actually reads from the list an exclusive locking with create inefficiencies. We have used AquireReaderLock in this case to create Shared locking for the block. Hence concurrent reads can took place only when no WriterLock is established, but concurrent writer locks are not possible.

The ReaderWriterLock also have method to escalate from Reader to Writer and vice versa using UpgradeToWriterLock or DowngradeFromWriterLock

Every lock should always specify its Release statement in finally.

I hope this would come handy.

Thanks for reading.

Abhishek Sur

Abhishek Sur is a Microsoft MVP since year 2011. He is an architect in the .NET platform. He has profound theoretical insight and years of hands on experience in different .NET products and languages. He leads the Microsoft User Group in Kolkata named KolkataGeeks, and regularly organizes events and seminars in various places for spreading .NET awareness. He is associated with the Microsoft Insider list on WPF and C#, and is in constant touch with product group teams. He blogs at http://www.abhisheksur.com His Book : Visual Studio 2012 and .NET 4.5 Expert Development Cookbook. Follow Abhishek at Twitter : @abhi2434

6 Comments to “Using ReaderWriterLock over Monitor for Thread Locking”

Comments are closed.