随笔-3  评论-5  文章-13  trackbacks-0

--------------------------------------------------------------------------------
标题: 在Win32平台中,多读单写锁如何实现?
作者: 叶飞虎
日期: 2004.03.17
--------------------------------------------------------------------------------

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

现给出读写锁代码,如下:

 

  1 /* TKYLockRW - 多读单写锁类 */
  2 
  3 class TKYLockRW
  4 {
  5 public:
  6    TKYLockRW();
  7    virtual ~TKYLockRW();
  8 
  9    bool              LockRead();
 10    bool              LockWrite();
 11 
 12    bool              TryLockRead();
 13    bool              TryLockWrite();
 14 
 15    void              UnlockRead();
 16    void              UnlockWrite();
 17 
 18 private:
 19    void              Lock()            { EnterCriticalSection(&FRWLock); }
 20    void              Unlock()          { LeaveCriticalSection(&FRWLock); }
 21 
 22    inline void       SetReadSignal();
 23    inline void       SetWriteSignal();
 24 
 25 private:
 26    CRITICAL_SECTION  FRWLock;
 27    HANDLE            FReaderEvent;
 28    HANDLE            FWriterEvent;
 29    long              FReadingCount;
 30    long              FWritingCount;
 31    long              FWaitingReadCount;
 32    long              FWaitingWriteCount;
 33 };
 34 
 35 /* TKYLockRW - 多读单写锁类 */
 36 
 37 // ---------------- 构造函数和析构函数 ----------------
 38 // 构造函数
 39 TKYLockRW::TKYLockRW()
 40 {
 41    // 初始化
 42    FReadingCount     = 0;
 43    FWritingCount     = 0;
 44    FWaitingReadCount = 0;
 45    FWaitingWriteCount= 0;
 46 
 47    // 创建临界区和读写者事件
 48    InitializeCriticalSection(&FRWLock);
 49    FReaderEvent      = CreateEvent(NULL, FALSE, FALSE, NULL);
 50    FWriterEvent      = CreateEvent(NULL, FALSE, FALSE, NULL);
 51 }
 52 
 53 // 析构函数
 54 TKYLockRW::~TKYLockRW()
 55 {
 56    // 置释放标志
 57    Lock();
 58    bool bWaiting = (FReadingCount > 0|| (FWritingCount == 1)
 59                                        || (FWaitingReadCount > 0)
 60                                        || (FWaitingWriteCount > 0);
 61    FReadingCount = -1;
 62    Unlock();
 63 
 64    // 等待一会儿
 65    if (bWaiting)
 66       Sleep(10);
 67 
 68    // 释放临界区和读写者事件
 69    CloseHandle(FReaderEvent);
 70    CloseHandle(FWriterEvent);
 71    DeleteCriticalSection(&FRWLock);
 72 }
 73 
 74 // ---------------- 私有方法 ----------------
 75 // 设置读信号
 76 inline void TKYLockRW::SetReadSignal()
 77 {
 78    // FWritingCount 作为读信号广播的个数
 79    if (FWritingCount == 0)
 80       FWritingCount = -FWaitingReadCount;
 81 
 82    // 是否需要继续广播
 83    if (FWritingCount < 0)
 84    {
 85       FWritingCount++;
 86       FReadingCount++;
 87       FWaitingReadCount--;
 88 
 89       SetEvent(FReaderEvent);
 90    }
 91 }
 92 
 93 // 设置写信号
 94 inline void TKYLockRW::SetWriteSignal()
 95 {
 96    FWritingCount = 1;
 97    FWaitingWriteCount--;
 98 
 99    SetEvent(FWriterEvent);
100 }
101 
102 // ---------------- 公有方法 ----------------
103 // 读加锁
104 bool TKYLockRW::LockRead()
105 {
106    bool result   = true;
107    bool bWaiting = false;
108 
109    // 读数加 1
110    Lock();
111    if (FReadingCount == -1)      // 释放标志
112       result = false;
113    else if ((FWritingCount == 1|| (FWaitingWriteCount > 0))
114    {
115       FWaitingReadCount++;
116       bWaiting = true;
117    }
118    else
119       FReadingCount++;
120    Unlock();
121 
122    // 判断是否等待读信号
123    if (bWaiting)
124    {
125       // 等待读信号
126       result = (WaitForSingleObject(FReaderEvent, INFINITE) == WAIT_OBJECT_0);
127 
128       if (result)
129       {
130          // 若广播个数不为零则继续置信号
131          Lock();
132          if (FWritingCount < 0)
133             SetReadSignal();
134          Unlock();
135       }
136    }
137 
138    // 返回结果
139    return result;
140 }
141 
142 // 写加锁
143 bool TKYLockRW::LockWrite()
144 {
145    bool result   = true;
146    bool bWaiting = false;
147 
148    // 写数置 1
149    Lock();
150    if (FReadingCount == -1)      // 释放标志
151       result = false;
152    else if ((FWritingCount == 1|| (FReadingCount > 0))
153    {
154       FWaitingWriteCount++;
155       bWaiting = true;
156    }
157    else
158       FWritingCount = 1;
159    Unlock();
160 
161    // 判断是否等待写信号
162    if (bWaiting)
163       result = (WaitForSingleObject(FWriterEvent, INFINITE) == WAIT_OBJECT_0);
164 
165    // 返回结果
166    return result;
167 }
168 
169 // 读试着加锁
170 bool TKYLockRW::TryLockRead()
171 {
172    bool result = true;
173 
174    // 读数加 1
175    Lock();
176    if ((FReadingCount == -1|| (FWritingCount == 1)
177                              || (FWaitingWriteCount > 0))
178       result = false;
179    else
180       FReadingCount++;
181    Unlock();
182 
183    // 返回结果
184    return result;
185 }
186 
187 // 写试着加锁
188 bool TKYLockRW::TryLockWrite()
189 {
190    bool result = true;
191 
192    // 写数置 1
193    Lock();
194    if ((FReadingCount == -1|| (FWritingCount == 1)
195                              || (FReadingCount > 0))
196       result = false;
197    else
198       FWritingCount = 1;
199    Unlock();
200 
201    // 返回结果
202    return result;
203 }
204 
205 // 读解锁
206 void TKYLockRW::UnlockRead()
207 {
208    Lock();
209    if (FReadingCount > 0)
210    {
211       // 读数减 1
212       FReadingCount--;
213 
214       // 置读/写信号
215       if (FReadingCount == 0)
216       {
217          if (FWaitingWriteCount > 0)
218             SetWriteSignal();
219          else
220             SetReadSignal();
221       }
222    }
223    Unlock();
224 }
225 
226 // 写解锁
227 void TKYLockRW::UnlockWrite()
228 {
229    Lock();
230    if (FWritingCount == 1)
231    {
232       // 写数置 0
233       FWritingCount = 0;
234 
235       // 置读/写信号
236       if (FWaitingWriteCount > FWaitingReadCount)
237          SetWriteSignal();
238       else
239          SetReadSignal();
240    }
241    Unlock();
242 }
243 
244 

 

posted on 2011-05-22 11:22 Kyee Ye 阅读(612) 评论(0)  编辑 收藏 引用 所属分类: C++类库KYLib 源码

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理