Gal Segal's Blog

Thoughts of a programmer with a soul

Oct 6

ReaderWriterLockSlim Extension Method

Tags:

locker

ReaderWriterLockSlim was introduced in .net 3.5 as a better and more stable locker that allows multiple reads and single write capabilities on a synced resource. Using it is fairly a simple task: for reader you wrap your resource with “EnterReadLock()” and “ExitReadLock()”, similar approach for writing.

One thing that is very important to remember is that you have to make sure the lock (either read or write) should be released after the action completes. The most obvious way is something like this:

var locker = new ReaderWriterLockSlim();
try
{
	locker.EnterReadLock();
}
finally
{
	locker.ExitWriteLock();
}

The problem is to enforce all programmers to do it every time they use the locker. There are some debates about a better syntax for doing so here, here and here. Basically we can solve it by wrapping the locking operation in another object that implements the  IDisposable interface and in the Dispose() method release the lock. The problem here is that there are some cases where The Dispose() method will not be called, as explained here.

A better, and more safe approach is something like this:  think of a read operation as a “getter” function that returns an object, and the write as a “setter” that receives an object, than wrap it up with extension method:

public static class ReadWriteLock
{
	public static T AcquireReadLock<T>(this ReaderWriterLockSlim locker, Func<T> action)
	{
		try
		{
			locker.EnterReadLock();
			return action();
		}
		finally
		{
			locker.ExitReadLock();
		}
	}

	public static void AcquireWriteLock(this ReaderWriterLockSlim locker, Action action)
	{
		try
		{
			locker.EnterWriteLock();
			action();
		}
		finally
		{
			locker.ExitWriteLock();
		}
	}
}

and usage:

var originalCollection = new List<string>{"apple","orange"};

//read
var replicatedData = locker.AcquireReadLock<List<string>>(() => originalCollection);

//write
locker.AcquireWriteLock(() => originalCollection.Add("banana"));

Happy coding :)

Back to top