Windows在Vista 和 Server2008以后才开始提供读写锁API,即SRW系列函数(InitializeSRWLock,AcquireSRWLockShared,AcquireSRWLockExclusive等)。
网上也有很多读写锁实现,基本上都是用互斥量对象和信号量对象实现。但是对于读写锁这种特殊的锁(锁住时间短)自旋的方式等待应该更合适,用Interlocked系列函数实现读写锁纯粹是因为闲的,也没有做过性能方面的测试,此实现是写优先的,如果不设计成写优先,写很难竞争到锁,是不合理的。。。
下面是源码:
#pragma once
///////////////////////////
class rwlock
{
public:
rwlock();
void r_lock();
void r_unlock();
void w_lock();
void w_unlock();
private:
//写锁
volatile long wlocks;
//写等待
volatile long wwaits;
//读锁
volatile long rlocks;
};
//////////////////////////
class rlock
{
public:
rlock(rwlock& lock);
~rlock();
private:
rwlock& _lock;
};
//////////////////////////
class wlock
{
public:
wlock(rwlock& lock);
~wlock();
private:
rwlock& _lock;
};
#include "rwlock.h"
#include <Windows.h>
rwlock::rwlock()
: wlocks(0)
, rlocks(0)
, wwaits(0)
{
}
void rwlock::r_lock()
{
//当前有写等待则不能进入读 写优先
while (InterlockedCompareExchange(&wwaits, 0, 0) != 0) {
Sleep(1);
}
//等待写释放
while (InterlockedExchange(&wlocks, 1) != 0) {
Sleep(1);
}
//读++
InterlockedIncrement(&rlocks);
//写释放
InterlockedExchange(&wlocks, 0);
}
void rwlock::r_unlock()
{
InterlockedDecrement(&rlocks);
}
void rwlock::w_lock()
{
if (InterlockedExchange(&wlocks, 1) != 0) {
//写等待++
InterlockedIncrement(&wwaits);
//等待写
while (InterlockedExchange(&wlocks, 1) != 0) {
Sleep(1);
}
//写等待--
InterlockedDecrement(&wwaits);
}
//等待读释放
while (InterlockedCompareExchange(&rlocks, 0, 0) != 0) {
Sleep(1);
}
}
void rwlock::w_unlock()
{
//写释放
InterlockedExchange(&wlocks, 0);
}
//////////////////////////////////////
rlock::rlock(rwlock & lock)
:_lock(lock)
{
_lock.r_lock();
}
rlock::~rlock()
{
_lock.r_unlock();
}
//////////////////////////////////////
wlock::wlock(rwlock & lock)
:_lock(lock)
{
_lock.w_lock();
}
wlock::~wlock()
{
_lock.w_unlock();
}