zhangJW_cn 阅读(1063) 评论(1)

下面代码是在windows实现的一个简单读写锁和非测试用例,贴出来供分享和参考。
说明:读写锁的目的在于针对读多写少的应用场合,减少锁同步的互斥等待成本。从代码可以看出如果读或写成本很低,直接用CRITICAL_SECTION成本更优。—— 如果没有锁同步争用,CRITICAL_SECTION的成本几乎为零(测试在Win 2003 EE上进行,单一主线程无争用)。

#include <windows.h>
#include <cassert>
#include <iostream>

class SimpleRWMutex
{
public:
 SimpleRWMutex( void ) : mRead( 0 )
 {
  ::InitializeCriticalSection( &mLock );
 }
 ~SimpleRWMutex( void )
 {
  ::DeleteCriticalSection( &mLock );
 }

 void lockWrite( void )
 { 
  for ( ::EnterCriticalSection(&mLock); mRead > 0; ::EnterCriticalSection(&mLock) )
  {
   ::LeaveCriticalSection( &mLock );
   ::Sleep( 0 );
  }
  assert( mRead == 0 );
 }
 void unlockWrite( void )
 {
  assert( mRead == 0 );
  ::LeaveCriticalSection( &mLock );
 }
 void lockRead( void )
 {
  ::EnterCriticalSection( &mLock );
  ++mRead;
  ::LeaveCriticalSection( &mLock );
 }
 void unlockRead( void )
 {
  ::EnterCriticalSection( &mLock );
  --mRead;
  ::LeaveCriticalSection( &mLock );
 }
 bool tryLockWrite( void )
 {
  BOOL succ = ::TryEnterCriticalSection( &mLock );
  if ( succ != TRUE ) return false;
  else if ( mRead <= 0 ) return true;
  else
  {
   ::LeaveCriticalSection( &mLock );
   return false;
  }
 }
 bool tryLockRead( void )
 {
  BOOL succ = ::TryEnterCriticalSection( &mLock );
  if ( succ != TRUE ) return false;
  else
  {
   ++mRead;
   ::LeaveCriticalSection( &mLock );
  }
 }

private:
 CRITICAL_SECTION mLock;
 volatile unsigned mRead;
};

#define WRITE 1000000
#define READ 2000

static unsigned num1 = 0,num2 = 0;
static unsigned num3 = 0,num4 = 0;
static DWORD WINAPI thread_write( void *arg )
{
 SimpleRWMutex  &mutex = *static_cast< SimpleRWMutex * >( arg );
 for ( unsigned i = 0; i < WRITE; ++i )
 {
  const bool sw = i % READ == 0;
  if ( mutex.tryLockWrite() )
  {
   if ( sw ) ::Sleep( 0 );
   ++num1;
   mutex.unlockWrite();
  }
  if ( sw ) ::Sleep( 0 );
  ++num2;
 }
 return 0;
}
static DWORD WINAPI thread_read( void *arg )
{
 SimpleRWMutex  &mutex = *static_cast< SimpleRWMutex * >( arg );
 for ( unsigned i = 0; i < READ; ++i )
 {
  mutex.lockRead();
//  std::cout << "num1 = " << num1 << " , num2 = " << num2 << std::endl;
  num3 += num1;
  mutex.unlockRead();
  num4 += num2;
  ::SwitchToThread();
 }
 return 0;
}

int main( int argc,char * argv[] )
{
 for ( unsigned i = 0; i < 10; ++i )
 {
  SimpleRWMutex  mutex;
  HANDLE   handle[] =
  {
   ::CreateThread( NULL,0,thread_write,&mutex,0,NULL ),
   ::CreateThread( NULL,0,thread_write,&mutex,0,NULL ),
   ::CreateThread( NULL,0,thread_read,&mutex,0,NULL ),
   ::CreateThread( NULL,0,thread_read,&mutex,0,NULL ),
  };
  const unsigned size = sizeof( handle ) / sizeof( HANDLE );

  thread_read( &mutex );

  ::WaitForMultipleObjectsEx( size,handle,TRUE,INFINITE,FALSE );
  for ( unsigned i = 0; i < size; ++i ) ::CloseHandle( handle[i] );

  std::cout << "finished with num1 = " << num1 << " , num2 = " << num2 << std::endl;
  std::cout << "finished with num3 = " << num3 << " , num4 = " << num4 << std::endl;
  std::cout << "--------------------------------------------------" << std::endl;
  num4 = num3 = num2 = num1 = 0;
 }
 return 0;
}


评论列表
Diviner
re: windows上的简单读写锁实现
win7 系统已经自带读写锁了。

发表评论
切换编辑模式