Locking for Reads and Writes in C#.NET (
Page 1 of 2 )
Jeff Cogswell shows you how you can easily implemnt a reader/writer lock in C#.NET. This is especially useful in ASP.NET.
I'm always surprised when I find open source and even commercial libraries where the authors have a note in the readme or web page that says something like, "The next version will add multi-threaded support." Many of these libraries are intended for ASP.NET, and having no multi-threaded support under ASP.NET is simply unacceptable. Besides, adding multi-threaded support really isn't all that difficult, so why not add it in the first place, right from the start? Often the problem is simply one of guarding objects that are shared by multiple threads and making sure the different threads don't walk all over each other. And that's not that difficult. In this article I show you how to make it happen.
Introducing ReaderWriterLock
When I first started working with multi-threaded applications in .NET, I spent some time fighting with some of the various classes for protecting shared memory. Months passed before I realized I was overlooking an incredibly useful class: The ReaderWriterLock class.
Think about this: Suppose you have a linked list that's shared between threads. If multiple threads are modifying the list simultaneously, you could have trouble. But what about reading? If several threads are trying to read the list simultaneously and nobody is changing it, then it's really not a problem, right? Really, the only time you have to be careful is when somebody needs to modify the list.
That's the basis behind the ReaderWriterLock. This class allows you to easily block threads such that only one thread is modifying an object at a time. When nobody is modifying the object, though, any thread is free to read the object.
Only one thread can modify the object at a time. Such threads request a writer lock. When a thread has a writer lock, no other threads and read or write the object. When the thread is finished modifying the object, it releases its write lock. If other threads are waiting to write, the next one in line gets access with a write lock and the other threads waiting will continue to wait, and so on. But if instead only threads that are waiting to read the resource need a lock, they will all be granted a lock.
In other words, only one thread and write to a resource at a time, but many threads can read a resource simultaneously.
Let's walk through some scenarios to make sure this is clear.
Some scnenarios
Suppose you have a linked list that is shared among all threads in an ASP.NET application. As different people browsing the web access your application, each will have a separate session, running as individual threads in your single application.
Now suppose one user starts an action that requires a modification to the list. But right at that moment other threads are looking at the list. The thread wanting to write will request a Writer Lock. At that point, the thread will block, while the threads reading the list will continue until they're finished reading the list. When they're done, the blocked thread needing write access will begin its code. During this time, no other thread can write or read the list. Any thread wanting to do either will block until this thread is finished with its writing. When it's finished, only then can the other threads proceed.
But what about the other threads wanting to read the list? How can they take part in this scenario? Before they attempt to read the list, they must request a Reader Lock on the object. Several threads can simultaneously have a Reader Lock on the object. If, while they have a lock, one thread wants to modify the data, that thread will request a Writer Lock, and will block until these threads are finished with their reading. When they're done reading, they will release their lock, and that's when the thread wanting to write will resume…and so on.
You can see from this picture why it makes sense that multiple Reader Locks can be issued simultaneously. But when writing needs to be done, only a single thread doing the writing has access to the resource. During that time, all other threads trying to access the resource will block.