See Also: ReaderWriterLock Members
The dnprdnshort has two reader-writer locks, System.Threading.ReaderWriterLockSlim and System.Threading.ReaderWriterLock. System.Threading.ReaderWriterLockSlim is recommended for all new development. System.Threading.ReaderWriterLockSlim is similar to System.Threading.ReaderWriterLock, but it has simplified rules for recursion and for upgrading and downgrading lock state. System.Threading.ReaderWriterLockSlim avoids many cases of potential deadlock. In addition, the performance of System.Threading.ReaderWriterLockSlim is significantly better than System.Threading.ReaderWriterLock.
System.Threading.ReaderWriterLock is used to synchronize access to a resource. At any given time, it allows either concurrent read access for multiple threads, or write access for a single thread. In a situation where a resource is changed infrequently, a ReaderWriterLock provides better throughput than a simple one-at-a-time lock, such as System.Threading.Monitor.
ReaderWriterLock works best where most accesses are reads, while writes are infrequent and of short duration. Multiple readers alternate with single writers, so that neither readers nor writers are blocked for long periods.
Holding reader locks or writer locks for long periods will starve other threads. For best performance, consider restructuring your application to minimize the duration of writes.
A thread can hold a reader lock or a writer lock, but not both at the same time. Instead of releasing a reader lock in order to acquire the writer lock, you can use ReaderWriterLock.UpgradeToWriterLock(int) and ReaderWriterLock.DowngradeFromWriterLock(LockCookie@).
Recursive lock requests increase the lock count on a lock.
Readers and writers are queued separately. When a thread releases the writer lock, all threads waiting in the reader queue at that instant are granted reader locks; when all of those reader locks have been released, the next thread waiting in the writer queue, if any, is granted the writer lock, and so on. In other words, ReaderWriterLock alternates between a collection of readers, and one writer.
While a thread in the writer queue is waiting for active reader locks to be released, threads requesting new reader locks accumulate in the reader queue. Their requests are not granted, even though they could share concurrent access with existing reader-lock holders; this helps protect writers against indefinite blockage by readers.
Most methods for acquiring locks on a ReaderWriterLock accept time-out values. Use time-outs to avoid deadlocks in your application. For example, a thread might acquire the writer lock on one resource and then request a reader lock on a second resource; in the meantime, another thread might acquire the writer lock on the second resource, and request a reader lock on the first. Unless time-outs are used, the threads deadlock.
If the time-out interval expires and the lock request has not been granted, the method returns control to the calling thread by throwing an ApplicationException. A thread can catch this exception and determine what action to take next.
Time-outs are expressed in milliseconds. If you use a TimeSpan to specify the time-out, the value used is the total number of whole milliseconds represented by the TimeSpan. The following table shows the valid time-out values in milliseconds.
-1 |
The thread waits until the lock is acquired, regardless of how long it takes. For methods that specify integer time-outs, the constant Timeout.Infinite can be used. |
0 |
The thread does not wait to acquire the lock. If the lock cannot be acquired immediately, the method returns. |
>0 |
The number of milliseconds to wait. |
With the exception of -1, negative time-out values are not allowed. If you specify a negative integer other than -1, a time-out value of zero is used instead. (That is, the method returns without waiting, if the lock cannot be acquired immediately.) If you specify a TimeSpan that represents a negative number of milliseconds other than -1, ArgumentOutOfRangeException is thrown.