读写锁的出现主要是在很多情况下,我们读资源的操作要多于写资源的操作。但是如果每次只对资源赋予一个线程的访问权限显然是低效的,读写锁的优势是同时可以有多个线程对同一资源进行读操作。因此在读操作比写操作多很多,并且写操作的时间很短的情况下使用读写锁是比较有效率的。读写锁是一个非静态类所以你在使用前需要先声明一个读写锁对象:
static
private
ReaderWriterLock _rwlock
=
new
ReaderWriterLock();
读写锁是通过调用AcquireReaderLock,ReleaseReaderLock,AcquireWriterLock,ReleaseWriterLock来完成读锁和写锁控制的
static
public
void
ReaderThread(
int
thrdId)
{
try
{ // 请求读锁,如果100ms超时退出
_rwlock.AcquireReaderLock( 10 );
try
{
int inx = _rand.Next(_list.Count);
if (inx < _list.Count)
Console.WriteLine( " {0}thread {1} " , thrdId, _list[inx]);
}
finally
{
_rwlock.ReleaseReaderLock();
}
}
catch (ApplicationException) // 如果请求读锁失败
{
Console.WriteLine( " {0}thread get reader lock out time! " , thrdId);
}
}
static public void WriterThread()
{
try
{
// 请求写锁
_rwlock.AcquireWriterLock( 100 );
try
{
string val = _rand.Next( 200 ).ToString();
_list.Add(val); // 写入资源
Console.WriteLine( " writer thread has written {0} " , val);
}
finally
{ // 释放写锁
_rwlock.ReleaseWriterLock();
}
}
catch (ApplicationException)
{
Console.WriteLine( " Get writer thread lock out time! " );
}
}
{
try
{ // 请求读锁,如果100ms超时退出
_rwlock.AcquireReaderLock( 10 );
try
{
int inx = _rand.Next(_list.Count);
if (inx < _list.Count)
Console.WriteLine( " {0}thread {1} " , thrdId, _list[inx]);
}
finally
{
_rwlock.ReleaseReaderLock();
}
}
catch (ApplicationException) // 如果请求读锁失败
{
Console.WriteLine( " {0}thread get reader lock out time! " , thrdId);
}
}
static public void WriterThread()
{
try
{
// 请求写锁
_rwlock.AcquireWriterLock( 100 );
try
{
string val = _rand.Next( 200 ).ToString();
_list.Add(val); // 写入资源
Console.WriteLine( " writer thread has written {0} " , val);
}
finally
{ // 释放写锁
_rwlock.ReleaseWriterLock();
}
}
catch (ApplicationException)
{
Console.WriteLine( " Get writer thread lock out time! " );
}
}
如果你想在读的时候插入写操作请使用UpgradeToWriterLock和DowngradeFromWriterLock来进行操作,而不是释放读锁。
static
private
void
UpgradeAndDowngrade(
int
thrdId)
{
try
{
_rwlock.AcquireReaderLock( 10 );
try
{
try
{
// 提升读锁到写锁
LockCookie lc = _rwlock.UpgradeToWriterLock( 100 );
try
{
string val = _rand.Next( 500 ).ToString();
_list.Add(val); Console.WriteLine( " Upgrade Thread{0} add {1} " , thrdId, val);
}
finally
{ // 下降写锁
_rwlock.DowngradeFromWriterLock( ref lc);
}
}
catch (ApplicationException)
{
Console.WriteLine( " {0}thread upgrade reader lock failed! " , thrdId);
}
}
finally
{
// 释放原来的读锁
_rwlock.ReleaseReaderLock();
}
}
catch (ApplicationException)
{
Console.WriteLine( " {0}thread get reader lock out time! " , thrdId);
}
}
{
try
{
_rwlock.AcquireReaderLock( 10 );
try
{
try
{
// 提升读锁到写锁
LockCookie lc = _rwlock.UpgradeToWriterLock( 100 );
try
{
string val = _rand.Next( 500 ).ToString();
_list.Add(val); Console.WriteLine( " Upgrade Thread{0} add {1} " , thrdId, val);
}
finally
{ // 下降写锁
_rwlock.DowngradeFromWriterLock( ref lc);
}
}
catch (ApplicationException)
{
Console.WriteLine( " {0}thread upgrade reader lock failed! " , thrdId);
}
}
finally
{
// 释放原来的读锁
_rwlock.ReleaseReaderLock();
}
}
catch (ApplicationException)
{
Console.WriteLine( " {0}thread get reader lock out time! " , thrdId);
}
}
这里有一点要注意的就是读锁和写锁的超时等待时间间隔的设置。通常情况下设置写锁的等待超时要比读锁的长,否则会经常发生写锁等待失败的情况。