Refer to '.NET Multithreading ALAN L. DENNIS' as core reference.
The name ReadWriteLock is misleading. It may cause you to think there are two locks; in reality there is a single lock that restricts both reading and writing.
A ReaderWriterLock allows multiple threads to read data at the same time. The only restriction is that a thread cannot modify the data while someone is reading it. In order words, a write lock is to ensure that no threads are reading data while it is being updated.
Therefore, it is wrong to use two different ReadWriteLock instances for reading and writing of the same subject.
But what if you first acquired read and before releasing it, you need to write ? (such as FIFO).
--> Make use of 'UpgradeToWriterLock'
But there is a problem, a value can change during the process of 'UpgradeToWriteLock'.
When the calling thread calls UpgradeToWriterLock? ? (step 4), the thread is removed from the list of active readers and placed in the pending writer requests queue (step 5). If a request from a different thread is already in the pending writer requests queue, it will be allowed to gain a write lock before the thread that requested the upgrade. The reason is the write lock requests are serviced in the order they are received, without any sort of priority associated with them. --> Pg 170 (.NET Multithreading ALAN L. DENNIS)
The problem is AcquireWriteLock will not return until it has successfully acquired a write lock and a write lock will not be granted until all read locks are released. Since the current thread has a read lock, it will never be able to acquire a write lock. This is a form of deadlock. It is unusual in that only one thread is required to form this deadlock. --> Pg 172. (.NET Multithreading ALAN L. DENNIS)
And it is not recommended to release the readlock before requesting the writelock because it will potentially result in race condition. Refer to the illustration below.
There is also 'DowngradeFromWriterLock'.
There is no possibility of change between the time DowngradeFromWriterLock? ? is called and the read lock is granted because when moving from a writer to a reader there is no chance that some other thread is already a reader, or can become one.This is not true when moving from a reader to a writer. In order to handle possible race conditions, UpgradeToWriterLock? ? uses the writer request queue.
--> Pg. 172 (.NET Multithreading ALAN L. DENNIS)
If a thread goes from being a reader to a writer and back to a reader, and stays in that state for an extended period of time, other threads will not be able to acquire a write lock. In general, locks should not be held the vast majority of the time, and only acquired when needed. The general rule of acquiring late and releasing early applies. Pg -->177 (.NET Multithreading ALAN L. DENNIS)
To solve the problem of "a value can change during the process of 'UpgradeToWriteLock'" mentioned earlier,
- If you need to do FIFO, make use of a system.collections.queue
- Alternatively, you can make use of 'WriterSeqNum' and 'AnyWritersSince' to find out if since your previous read there has been other writing done. Refer to Pg. 177(.NET Multithreading ALAN L. DENNIS)