C++读写锁,难道不用mutex也可以实现么?大家看一个读写锁的类声明class CLockerRW{protected:volatile boos
C++读写锁,难道不用mutex也可以实现么?
大家看一个读写锁的类声明
class CLockerRW{
protected:
volatile boost::uint32_t reader_count;
volatile boost::uint32_t want_2_write;
public:
CLockerRW();
void LockRead();
void FreeRead();
void LockWrite();
void FreeWrite();
};这样也可以实现读写锁么?让我写的话,一定会借助mutex配合contidion来实现。求高手给一个思路。
[解决办法]
//比如一个全局变量int gUse=0;
//线程1:
while (1) {
if (gUse==0) {
gUse=1;
if (gUse==1) {
//进入临界区
//...
gUse=0;//退出临界区
break;
}
}
Sleep(100);
}
//线程2:
while (1) {
if (gUse==0) {
gUse=2;
if (gUse==2) {
//进入临界区
//...
gUse=0;//退出临界区
break;
}
}
Sleep(100);
}
[解决办法]
先谈一下效率问题,假设楼主不想用Mutex是出于效率考虑:
我所知的Mutex效率问题主要是会导致调用线程在用户态和内核态之间的切换。那么假设LZ需要的是一个纯用户态的锁。
为了避免进入内核态,所有依赖于内核对象的方法(Mutex, Event, etc.)都不能用。实际上,Sleep()函数对线程的挂起和唤醒也是内核态的代码。所以Sleep()也不能用。不能挂起线程,就意味着线程即使在阻塞状态,什么实事也不干的时候,也不得不消耗CPU——至少要执行空指令。所以纯用户态的锁只有在预计线程不会被长时间阻塞的时候才真正得有效率。
改进8楼的代码:
8楼的代码想法已经很清晰了,实现上有一点问题,赋值和判断语句加在一起不是一个原子操作。这里所谓原子操作,准确说是对于线程调度而言。即不会被线程调度打断的操作,就是一个原子操作。线程调度是windows来做的,所以要实现原子操作,至少要在windows这一层实现,100%自制代码是不可能的。还好windows有提供一套InterlockedXXX函数来实现原子操作,而且它们都是用户态的!具体改动如下:
//线程1:
while (1) {
InterlockedCompareExchange(&gUse, 1, 0);
if (gUse==1) {
//进入临界区
cout << "I'm thread 1" << endl; // do my work
InterlockedExchange(&gUse, 0);//退出临界区
break;
}
_asm nop; // 空指令,可以多放几个,其实可有可无,反正是要耗CPU的
}
//线程2:
while (1) {
InterlockedCompareExchange(&gUse, 2, 0);
if (gUse==2) {
//进入临界区
cout << "I'm thread 2" << endl; // do my work
InterlockedExchange(&gUse, 0);//退出临界区
break;
}
_asm nop; // 空指令,可以多放几个,其实可有可无,反正是要耗CPU的
}
更进一步的,到底一个普通的赋值操作在多核或者多CPU上是不是原子的,我也不确定,请牛人解释了。这里把所有赋值都换成InterlockedExchange,把这个责任交给了windows。
