public void AcquireReaderLock( int millisecondsTimeout ) { // m_mutext 很快能夠獲得,以便進入臨界區 m_mutex.WaitOne( ); // 是否有寫入線程存在 bool bExistingWriter = ( m_nActive < 0 ); if( bExistingWriter ) { //等待閱讀線程數目加1,當有鎖釋放時,根據此數目來調度線程 m_nWaitingReaders++; } else { //當前活動線程加 m_nActive++; } m_mutex.ReleaseMutex(); //存儲鎖標誌爲Reader System.LocalDataStoreSlot slot = Thread.GetNamedDataSlot(m_strThreadSlotName); object obj = Thread.GetData( slot ); LockFlags flag = LockFlags.None; if( obj != null ) flag = (LockFlags)obj ; if( flag == LockFlags.None ) { Thread.SetData( slot, LockFlags.Reader ); } else { Thread.SetData( slot, (LockFlags)((int)flag | (int)LockFlags.Reader ) ); } if( bExistingWriter ) { //等待指定的時間 this.m_aeReaders.WaitOne( millisecondsTimeout, true ); } } |
public void AcquireWriterLock( int millisecondsTimeout ) { // m_mutext 很快能夠獲得,以便進入臨界區 m_mutex.WaitOne( ); // 是否有活動線程存在 bool bNoActive = m_nActive == 0; if( !bNoActive ) { m_nWaitingWriters++; } else { m_nActive--; } m_mutex.ReleaseMutex(); //存儲線程鎖標誌 System.LocalDataStoreSlot slot = Thread.GetNamedDataSlot( "myReaderWriterLockDataSlot" ); object obj = Thread.GetData( slot ); LockFlags flag = LockFlags.None; if( obj != null ) flag = (LockFlags)Thread.GetData( slot ); if( flag == LockFlags.None ) { Thread.SetData( slot, LockFlags.Writer ); } else { Thread.SetData( slot, (LockFlags)((int)flag | (int)LockFlags.Writer ) ); } //若是有活動線程,等待指定的時間 if( !bNoActive ) this.m_aeWriters.WaitOne( millisecondsTimeout, true ); } |
public void ReleaseReaderLock() { System.LocalDataStoreSlot slot = Thread.GetNamedDataSlot(m_strThreadSlotName ); LockFlags flag = (LockFlags)Thread.GetData( slot ); if( flag == LockFlags.None ) { return; } bool bReader = true; switch( flag ) { case LockFlags.None: break; case LockFlags.Writer: bReader = false; break; } if( !bReader ) return; Thread.SetData( slot, LockFlags.None ); m_mutex.WaitOne(); AutoResetEvent autoresetevent = null; this.m_nActive --; if( this.m_nActive == 0 ) { if( this.m_nWaitingReaders > 0 ) { m_nActive ++ ; m_nWaitingReaders --; autoresetevent = this.m_aeReaders; } else if( this.m_nWaitingWriters > 0) { m_nWaitingWriters--; m_nActive --; autoresetevent = this.m_aeWriters ; } } m_mutex.ReleaseMutex(); if( autoresetevent != null ) autoresetevent.Set(); } |
using System;
using System.Threading; using MyThreading; class Resource { myReaderWriterLock rwl = new myReaderWriterLock(); public void Read(Int32 threadNum)
{
rwl.AcquireReaderLock(Timeout.Infinite); try
{
Console.WriteLine("Start Resource reading (Thread={0})", threadNum); Thread.Sleep(250); Console.WriteLine("Stop Resource reading (Thread={0})", threadNum);
}
finally
{
rwl.ReleaseReaderLock(); } } public void Write(Int32 threadNum)
{
rwl.AcquireWriterLock(Timeout.Infinite); try
{
Console.WriteLine("Start Resource writing (Thread={0})", threadNum); Thread.Sleep(750); Console.WriteLine("Stop Resource writing (Thread={0})", threadNum);
}
finally
{
rwl.ReleaseWriterLock(); } } } class App
{
static Int32 numAsyncOps = 20; static AutoResetEvent asyncOpsAreDone = new AutoResetEvent(false); static Resource res = new Resource(); public static void Main()
{
for (Int32 threadNum = 0; threadNum < 20; threadNum++)
{ ThreadPool.QueueUserWorkItem(new WaitCallback(UpdateResource), threadNum); } asyncOpsAreDone.WaitOne(); Console.WriteLine("All operations have completed."); Console.ReadLine(); } // The callback method's signature MUST match that of a System.Threading.TimerCallback // delegate (it takes an Object parameter and returns void) static void UpdateResource(Object state) { Int32 threadNum = (Int32) state; if ((threadNum % 2) != 0) res.Read(threadNum); else res.Write(threadNum); if (Interlocked.Decrement(ref numAsyncOps) == 0) asyncOpsAreDone.Set(); } } |