参看我前一篇文章:http://blog.csdn.net/tifentan/article/details/78949028
这里再提供一个跨平台的简单实现:
//完成读写锁初始化
CRWLock::CRWLock()
{
InitRWLock();
}
//
CRWLock::~CRWLock()
{
DestroyRWLock();
}
BOOL CRWLock::MyWaitForSingleObject(HANDLE hObject)
{
#ifdef WIN32
DWORD result;
result = WaitForSingleObject(hObject, INFINITE);
return (result == WAIT_OBJECT_0);
#endif
}
BOOL CRWLock::InitRWLock()
{
#ifdef WIN32
m_RWLock.nReaderCount = 0;
m_RWLock.hDataLock = CreateSemaphore(NULL, 1, 1, NULL);
if (m_RWLock.hDataLock == NULL)
{
return FALSE;
}
m_RWLock.hMutex = CreateMutex(NULL, FALSE, NULL);
if (m_RWLock.hMutex == NULL)
{
CloseHandle(m_RWLock.hDataLock);
return FALSE;
}
return TRUE;
#else
pthread_rwlock_init(&m_RWLock, NULL);
return TRUE;
#endif
}
BOOL CRWLock::DestroyRWLock()
{
#ifdef WIN32
DWORD result = WaitForSingleObject(m_RWLock.hDataLock, INFINITE);
if (result != WAIT_OBJECT_0)
{
return FALSE;
}
CloseHandle(m_RWLock.hMutex);
CloseHandle(m_RWLock.hDataLock);
return TRUE;
#else
pthread_rwlock_destroy(&m_RWLock);
return TRUE;
#endif
}
BOOL CRWLock::AcquireReadLock()
{
BOOL result = TRUE;
#ifdef WIN32
if (MyWaitForSingleObject(m_RWLock.hMutex) == FALSE)
{
return FALSE;
}
m_RWLock.nReaderCount ++;
if(m_RWLock.nReaderCount == 1)
{
result = MyWaitForSingleObject(m_RWLock.hDataLock);
}
ReleaseMutex(m_RWLock.hMutex);
return result;
#else
pthread_rwlock_rdlock(&m_RWLock);
return result;
#endif
}
BOOL CRWLock::ReleaseReadLock()
{
int result = TRUE;
#ifdef WIN32
LONG lPrevCount;
if (MyWaitForSingleObject(m_RWLock.hMutex) == FALSE)
{
return FALSE;
}
--m_RWLock.nReaderCount;
if (m_RWLock.nReaderCount == 0)
{
result = ReleaseSemaphore(m_RWLock.hDataLock, 1, &lPrevCount);
}
ReleaseMutex(m_RWLock.hMutex);
return result;
#else
return pthread_rwlock_unlock(&m_RWLock);
#endif
}
BOOL CRWLock::AcquireWriteLock()
{
#ifdef WIN32
return MyWaitForSingleObject(m_RWLock.hDataLock);
#else
return pthread_rwlock_wrlock(&m_RWLock);
#endif
}
BOOL CRWLock::ReleaseWriteLock()
{
#ifdef WIN32
int result = TRUE;
LONG lPrevCount;
result = ReleaseSemaphore(m_RWLock.hDataLock, 1, &lPrevCount);
if (lPrevCount != 0)
{
return FALSE;
}
return result;
#else
return pthread_rwlock_unlock(&m_RWLock);
#endif
}
然而这个是有问题的,多个读线程高频率读,写锁有可能进入不了。
解决方法是再建立一个mutex来管理资源状态,确认有更新数据才进入读锁。
关于读写的优先问题
以下两种情况下读写请求会进行竞争:
1.释放写锁后
2.在读锁状态下,有写锁请求会等待,之后再有新的读锁请求将一同等待,当读锁状态释放后
会不会同时有读写锁请求的情况下,优先写锁会好点呢?
上篇文章是公平竞争的,如果要求写优先,可参考https://www.cnblogs.com/kuliuheng/p/4065304.html的linux部分,关键在于使用到一个状态锁,两个条件事件。
修改后代码如下:
//写优先读写锁
class RWLockAdv
{
private:
int _st;
int _rlockCount;
int _rwaitingCount;
int _wwaitingCount;
HANDLE _wev;
HANDLE _rev;
#ifdef CROSS_PROCESS_IPC
HANDLE _stLock;
#else
CRITICAL_SECTION _stLock;
#endif
public:
RWLockAdv(void);
~RWLockAdv(void);
void rlock();
void wlock();
void unlock();
};
#define RWLOCK_IDLE 0
#define RWLOCK_R 0x01
#define RWLOCK_W 0x02
RWLockAdv::RWLockAdv(void)
: _rlockCount(0),
_st(RWLOCK_IDLE),
_rwaitingCount(0),
_wwaitingCount(0)
{
#ifdef CROSS_PROCESS_IPC
_stLock = CreateMutex(NULL, FALSE, NULL);
assert(_stLock != INVALID_HANDLE_VALUE);
#else
InitializeCriticalSection(&_stLock);
#endif
_wev = CreateEvent(NULL, TRUE, FALSE, NULL);
assert(_wev != INVALID_HANDLE_VALUE);
_rev = CreateEvent(NULL, TRUE, FALSE, NULL);
assert(_rev != INVALID_HANDLE_VALUE);
}
RWLockAdv::~RWLockAdv(void)
{
#ifdef CROSS_PROCESS_IPC
CloseHandle(_stLock);
#else
DeleteCriticalSection(&_stLock);
#endif
CloseHandle(_wev);
CloseHandle(_rev);
}
void RWLockAdv::rlock()
{
bool isWaitReturn = false;
while (1)
{
#ifdef CROSS_PROCESS_IPC
WaitForSingleObject(_stLock, INFINITE);
#else
EnterCriticalSection(&_stLock);
#endif
if (isWaitReturn)
{
--_rwaitingCount;
}
if (_st == RWLOCK_IDLE)
{
_st = RWLOCK_R;
_rlockCount++;
#ifdef CROSS_PROCESS_IPC
ReleaseMutex(_stLock);
#else
LeaveCriticalSection(&_stLock);
#endif
break;
}
else if (_st == RWLOCK_R)
{
if (_wwaitingCount > 0)
{
++_rwaitingCount;
ResetEvent(_rev);
#ifdef CROSS_PROCESS_IPC
SignalObjectAndWait(_stLock, _rev, INFINITE, FALSE);
#else
LeaveCriticalSection(&_stLock);
WaitForSingleObject(_rev, INFINITE);
#endif
isWaitReturn = true;
}
else
{
++_rlockCount;
#ifdef CROSS_PROCESS_IPC
ReleaseMutex(_stLock);
#else
LeaveCriticalSection(&_stLock);
#endif
break;
}
}
else if (_st == RWLOCK_W)
{
++_rwaitingCount;
ResetEvent(_rev);
#ifdef CROSS_PROCESS_IPC
SignalObjectAndWait(_stLock, _rev, INFINITE, FALSE);
#else
LeaveCriticalSection(&_stLock);
WaitForSingleObject(_rev, INFINITE);
#endif
isWaitReturn = true;
}
else
{
assert(0);
break;
}
}
}
void RWLockAdv::wlock()
{
bool isWaitReturn = false;
while (1)
{
#ifdef CROSS_PROCESS_IPC
WaitForSingleObject(_stLock, INFINITE);
#else
EnterCriticalSection(&_stLock);
#endif
if (isWaitReturn) --_wwaitingCount;
if (_st == RWLOCK_IDLE)
{
_st = RWLOCK_W;
#ifdef CROSS_PROCESS_IPC
ReleaseMutex(_stLock);
#else
LeaveCriticalSection(&_stLock);
#endif
break;
}
else
{
++_wwaitingCount;
ResetEvent(_wev);
#ifdef CROSS_PROCESS_IPC
SignalObjectAndWait(_stLock, _wev, INFINITE, FALSE);
#else
LeaveCriticalSection(&_stLock);
WaitForSingleObject(_wev, INFINITE);
#endif
isWaitReturn = true;
}
}
}
void RWLockAdv::unlock()
{
#ifdef CROSS_PROCESS_IPC
WaitForSingleObject(_stLock, INFINITE);
#else
EnterCriticalSection(&_stLock);
#endif
//这代表在读状态
if (_rlockCount > 0)
{
--_rlockCount;
if (0 == _rlockCount)
{
_st = RWLOCK_IDLE;
if (_wwaitingCount > 0) {
SetEvent(_wev);
}
else if(_rwaitingCount > 0){
SetEvent(_rev);
}
else
{
}
}
else
{
}
}
else
{
_st = RWLOCK_IDLE;
//也可以改成写状态释放后优先读?
if (_wwaitingCount > 0) {
SetEvent(_wev);
}
else if (_rwaitingCount > 0) {
SetEvent(_rev);
}
else
{
}
}
#ifdef CROSS_PROCESS_IPC
ReleaseMutex(_stLock);
#else
LeaveCriticalSection(&_stLock);
#endif
}
代码没测试,待续!!!