--------------------------------------------------------------------------------
标题: 在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 、
源码