在Win32平台中,多读单写锁如何使用临界区实现?

来源:互联网 发布:微信兵工厂软件 编辑:程序博客网 时间:2024/05/23 23:03

--------------------------------------------------------------------------------
标题: 在Win32平台中,多读单写锁如何使用临界区实现?
作者: 叶飞虎
日期: 2011.11.11
--------------------------------------------------------------------------------

   在多线程编程中,读写锁主要应用于写数据相对比较少,而读比较多,同时要求并发性
比较高的时候。

 

现给出使用临界区的读写锁代码,如下:

class TKYLockRWEx{public:   TKYLockRWEx();   virtual ~TKYLockRWEx();   bool              LockRead();   bool              LockWrite();   bool              TryLockRead();   bool              TryLockWrite();   void              UnlockRead();   void              UnlockWrite();private:   void              Lock()            { EnterCriticalSection(&FRWLock); }   void              Unlock()          { LeaveCriticalSection(&FRWLock); }   void              WaitingReader()   { EnterCriticalSection(&FLockReader); }   void              WaitingWriter()   { EnterCriticalSection(&FLockWriter); }   inline void       SetReadSignal();   inline void       SetWriteSignal();private:   CRITICAL_SECTION  FRWLock;   CRITICAL_SECTION  FLockReader;   CRITICAL_SECTION  FLockWriter;   long              FReadingCount;   long              FWritingCount;   long              FWaitingReadCount;   long              FWaitingWriteCount;};// ---------------- 构造函数和析构函数 ----------------// 构造函数TKYLockRWEx::TKYLockRWEx(){   // 初始化   FReadingCount     = 0;   FWritingCount     = 0;   FWaitingReadCount = 0;   FWaitingWriteCount= 0;   // 创建临界区和读写者   InitializeCriticalSection(&FRWLock);   InitializeCriticalSection(&FLockReader);   InitializeCriticalSection(&FLockWriter);}// 析构函数TKYLockRWEx::~TKYLockRWEx(){   // 置释放标志   Lock();   bool bWaiting = (FReadingCount > 0) || (FWritingCount == 1)                                       || (FWaitingReadCount > 0)                                       || (FWaitingWriteCount > 0);   FReadingCount = -1;   Unlock();   // 等待一会儿   if (bWaiting)      Sleep(10);   // 释放临界区和读写者   DeleteCriticalSection(&FLockWriter);   DeleteCriticalSection(&FLockReader);   DeleteCriticalSection(&FRWLock);}// ---------------- 私有方法 ----------------// 设置读信号inline void TKYLockRWEx::SetReadSignal(){   // FWritingCount 作为读信号广播的个数   if (FWritingCount == 0)      FWritingCount = -FWaitingReadCount;   // 是否需要继续广播   if (FWritingCount < 0)   {      FWritingCount++;      FReadingCount++;      FWaitingReadCount--;      LeaveCriticalSection(&FLockReader);   }   else if (FWaitingWriteCount == 0)   // 全部已退出锁   {      LeaveCriticalSection(&FLockReader);      LeaveCriticalSection(&FLockWriter);   }}// 设置写信号inline void TKYLockRWEx::SetWriteSignal(){   FWritingCount = 1;   FWaitingWriteCount--;   LeaveCriticalSection(&FLockWriter);}// ---------------- 公有方法 ----------------// 读加锁bool TKYLockRWEx::LockRead(){   bool result   = true;   bool bWaiting = false;   // 读数加 1   Lock();   if (FReadingCount == -1)      // 释放标志      result   = false;   else if ((FWritingCount == 1) || (FWaitingWriteCount > 0))   {      FWaitingReadCount++;      bWaiting = true;   }   else if (++FReadingCount == 1)   {      WaitingWriter();      WaitingReader();   }   Unlock();   // 判断是否等待读信号   if (bWaiting)   {      // 等待读信号      WaitingReader();      // 若广播个数不为零则继续置信号      Lock();      if (FWritingCount < 0)         SetReadSignal();      Unlock();   }   // 返回结果   return result;}// 写加锁bool TKYLockRWEx::LockWrite(){   bool result   = true;   bool bWaiting = false;   // 写数置 1   Lock();   if (FReadingCount == -1)      // 释放标志      result   = false;   else if ((FWritingCount == 1) || (FReadingCount > 0))   {      FWaitingWriteCount++;      bWaiting = true;   }   else   {      FWritingCount = 1;      WaitingWriter();      WaitingReader();   }   Unlock();   // 判断是否等待写信号   if (bWaiting)      WaitingWriter();   // 返回结果   return result;}// 读试着加锁bool TKYLockRWEx::TryLockRead(){   bool result = true;   // 读数加 1   Lock();   if ((FReadingCount == -1) || (FWritingCount == 1)                             || (FWaitingWriteCount > 0))      result = false;   else if (++FReadingCount == 1)   {      WaitingWriter();      WaitingReader();   }   Unlock();   // 返回结果   return result;}// 写试着加锁bool TKYLockRWEx::TryLockWrite(){   bool result = true;   // 写数置 1   Lock();   if ((FReadingCount == -1) || (FWritingCount == 1)                             || (FReadingCount > 0))      result = false;   else   {      FWritingCount = 1;      WaitingWriter();      WaitingReader();   }   Unlock();   // 返回结果   return result;}// 读解锁void TKYLockRWEx::UnlockRead(){   Lock();   if (FReadingCount > 0)   {      // 读数减 1      FReadingCount--;      // 置读/写信号      if (FReadingCount == 0)      {         if (FWaitingWriteCount > 0)            SetWriteSignal();         else            SetReadSignal();      }   }   Unlock();}// 写解锁void TKYLockRWEx::UnlockWrite(){   Lock();   if (FWritingCount == 1)   {      // 写数置 0      FWritingCount = 0;      // 置读/写信号      if (FWaitingWriteCount > FWaitingReadCount)         SetWriteSignal();      else         SetReadSignal();   }   Unlock();}



注:
    使用临界区的读写锁代码是从使用 Event 的 TKYLockRW 类更改而来, 未经验证是否正
确, 本人只是从逻辑上确认没有bug, 倘若真的存在 bug, 欢迎拍砖指正!

 

原创粉丝点击