技术开发 频道

C#多线程编程实例编程

  申请写入锁的函数原型为:public void AcquireWriterLock( int millisecondsTimeout ),其中的参数为等待调度的时间。函数定义如下: 

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 );    
}

  它首先进入临界区判断当前活动线程的数目,如果当前有活动线程存在,不管是写线程还是读线程(m_nActive),线程将等待指定的时间并且等待的写入线程数目加1,否则线程拥有写的权限。

释放阅读锁的函数原型为:public void ReleaseReaderLock()。函数定义如下: 

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();    
}

  释放阅读锁时,首先判断当前线程是否拥有阅读锁(通过线程局部存储的标志),然后判断是否有等待的阅读线程,如果有,先将当前活动线程加1,等待阅读线程数 目减1,然后置事件为有信号。如果没有等待的阅读线程,判断是否有等待的写入线程,如果有则活动线程数目减1,等待的写入线程数目减1。释放写入锁与释放 阅读锁的过程基本一致,可以参看源代码。

  注意在程序中,释放锁时,只会唤醒一个阅读程序,这是因为使用AutoResetEvent的原历,读者可自行将其改成ManualResetEvent,同时唤醒多个阅读程序,此时应令m_nActive等于整个等待的阅读线程数目。

0
相关文章