ReaderWriterLock 用於同步存取資源。
它能在任何指定時間並行讀取多重執行緒或寫入單一執行緒。 如果資源不常變更, ReaderWriterLock 的產量優於每次一的鎖定 (例如 Monitor )。
如果不常寫入 (而且寫入時間很短) 而是以讀取為主,則 ReaderWriterLock 最適合。 多重讀取器和單一寫入器交替,就不會長期鎖定讀取器和寫入器。
執行緒可以保留讀取器鎖定或寫入器鎖定,但不能同時執行。
與其釋放讀取器鎖定取得寫入器鎖定,您不妨使用 UpgradeToWriterLock 和 DowngradeFromWriterLock 。
遞迴鎖定要求會增加鎖定上的鎖定計數。
讀取器和寫入器是個別佇列。 執行緒釋放寫入器鎖定時,在讀取器佇列中等候的所有執行緒都會獲得讀取器鎖定;釋放所有讀取器鎖定時,在寫入器佇列中等候的下一個執行緒 (若有) 會獲得寫入器鎖定,以此類推。 換言之, ReaderWriterLock 在讀取器集合和寫入器集合之間交替。
寫入器佇列中的執行緒正在等候釋放讀取器鎖定時,要求新讀取器鎖定的執行緒也不斷在讀取器佇列中累積。 即使這些要求可以和現有讀取器鎖定的持有人共用並行存取,卻仍然不會同意這些要求;此一措施可以協助避免讀取器持續鎖定寫入器的情況。
大部分取得鎖定 ReaderWriterLock 的方法會接受逾時值。 逾時可用來避免應用程式鎖死。 例如,執行緒可能在一個資源上取得寫入器鎖定,並在第二個資源上取得讀取器鎖定;同時可能有另一個執行緒在第二個資源上取得寫入器鎖定,並在第一個資源上取得讀取器鎖定。 此時除非使用逾時,否則執行緒會鎖死。
如果逾時間隔到期但鎖定要求並未獲准,這個方法會擲回 ApplicationException ,將控制項傳回至呼叫執行緒。 執行緒可以攔截這個例外狀況,並決定下一個採取動作。
逾時值是以毫秒為單位。 如果您使用 System . TimeSpan 指定逾時,則會使用 TimeSpan 表示的毫秒總整數。 下表顯示有效的逾時值 (以毫秒為單位)。
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
// 读线程锁
static ReaderWriterLock m_ReadLock = new ReaderWriterLock();
static ReaderWriterLock m_WriteLock = new ReaderWriterLock();
// 资源
static int m_nResource = 0 ;
// 读取资源线程
static void ReadProc()
{
for ( int i = 0 ; i < 5 ; i ++ )
{
ReadResource( 5000 );
Thread.Sleep( 500 );
}
}
// 写入资源线程
static void WriteProc()
{
for ( int i = 0 ; i < 5 ; i ++ )
{
WriteResource( 5000 );
Thread.Sleep( 500 );
}
}
// 读取资源
private static bool ReadResource( int timeout)
{
try
{
m_ReadLock.AcquireReaderLock(timeout);
try
{
Console.WriteLine( " 成功获得读线程锁, 资源值:{0} " , m_nResource);
}
finally
{
m_ReadLock.ReleaseReaderLock();
}
}
catch (ApplicationException ex)
{
Console.WriteLine( " 获取锁超时:{0} " , ex.Message);
}
catch (Exception ex)
{
Console.WriteLine( " 获取锁异常:{0} " , ex.Message);
}
return true ;
}
// 写入资源
private static bool WriteResource( int timeout)
{
try
{
m_WriteLock.AcquireWriterLock(timeout);
try
{
Console.WriteLine( " 成功获得写线程锁, 资源值:{0} " , m_nResource);
m_nResource ++ ;
Console.WriteLine( " 写入资源 {0} " , m_nResource);
}
finally
{
m_WriteLock.ReleaseWriterLock();
}
}
catch (ApplicationException ex)
{
Console.WriteLine( " 获取锁超时:{0} " , ex.Message);
}
catch (Exception ex)
{
Console.WriteLine( " 获取锁异常:{0} " , ex.Message);
}
return true ;
}
static void Main( string [] args)
{
Thread t1 = new Thread( new ThreadStart(ReadProc));
Thread t2 = new Thread( new ThreadStart(WriteProc));
t1.Start();
t2.Start();
Thread.Sleep( 5000 );
Console.WriteLine( " 按任意键退出... " );
Console.ReadKey();
}
}
}