您的位置:首页 > 理论基础 > 数据结构算法

绞尽脑汁写的一个自认为非常简洁高效的读写锁

2009-03-20 03:31 381 查看
以前的工作中用到过几次读写锁,自己还曾实现过一两个版本(现在回头看看都很垃圾),剩下大部分用别人库里的。
两个月前一个小项目里需要一个读写锁,对效率要求很高。某天下午终于花了几个小时的时间设计出这么一个东东,理论上看,非常简洁高效,但逻辑较混乱……没办法为了高效嘛,只好牺牲点了。

其后的几天,通过写程序来完全模拟读写锁行为,发现了多个逻辑错误导致死锁或未锁的情况, 好在最后牺牲了更多的脑细胞后,终于完成了一个严格通过模拟逻辑测试的版本。

简单介绍下,能想到的,这个读写锁的特点:
一、数据结构简单,仅使用两个event对象和两个计数变量,整个读写锁共16字节大小。实现部分只有50多行代码。
二、作为写优先的读写锁,支持多个写线程。
三、其工作方式非常高效。在没有线程执行写操作时,其读锁的获取和释放过程不产生任何系统调用。
四、整个工作过程不存在轮询等待——正常地写都如此吧,无奈翻翻我以前写过的第一个读写锁程序……汗。

五、可以通过简单的修改,将两个event对象命名,且移动两个计数变量到共享内存中,即可在多个进程间使用。

 

以下是源码:

/********************************************************************
created:	2009/01/16
created:	16:1:2009   3:35
name:       ReadWriteLock 1.0
filename: 	ReadWriteLock.h
author:		Foreverflying
*********************************************************************/

#pragma once
#include <intrin.h>

class ReadWriteLock
{
public:
ReadWriteLock(void);
~ReadWriteLock(void);

void GetReadLock();
void ReleaseReadLock();
void GetWriteLock();
void ReleaseWriteLock();

private:
BOOL StopRead_WaitSetWrite();
HANDLE _canReadEvent;
HANDLE _canWriteEvent;
volatile LONG _readCount;
volatile LONG _writeCount;
};

#define CAN_NOT_READ_SIGN   0x80000000
#define CAN_NOT_WRITE_SIGN  0x40000000
#define READ_COUNT_MASK     0x3fffffff

ReadWriteLock::ReadWriteLock(void)
: _readCount(0)
, _writeCount(0)
{
_canReadEvent = CreateEvent( NULL, TRUE, TRUE, NULL );
_canWriteEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
}

ReadWriteLock::~ReadWriteLock( void )
{
CloseHandle( _canReadEvent );
CloseHandle( _canWriteEvent );
}

void ReadWriteLock::GetReadLock()
{
while(1){
LONG count = InterlockedIncrement( &_readCount );
if( count < 0 ){
InterlockedDecrement( &_readCount );
count = InterlockedCompareExchange( &_readCount, CAN_NOT_READ_SIGN,
CAN_NOT_READ_SIGN | CAN_NOT_WRITE_SIGN );
if( count == (CAN_NOT_READ_SIGN | CAN_NOT_WRITE_SIGN) ){
SetEvent( _canWriteEvent );
}
WaitForSingleObject( _canReadEvent, INFINITE );
}else{
return;
}
}
}

void ReadWriteLock::ReleaseReadLock()
{
InterlockedDecrement( &_readCount );
LONG count = InterlockedCompareExchange( &_readCount, CAN_NOT_READ_SIGN,
CAN_NOT_READ_SIGN | CAN_NOT_WRITE_SIGN );
if( count == (CAN_NOT_READ_SIGN | CAN_NOT_WRITE_SIGN) ){
SetEvent( _canWriteEvent );
}
}

void ReadWriteLock::GetWriteLock()
{
LONG count = InterlockedIncrement( &_writeCount );
if( count == 1 ){
if( !StopRead_WaitSetWrite() ){
return;
}
}
WaitForSingleObject( _canWriteEvent, INFINITE );
}

void ReadWriteLock::ReleaseWriteLock()
{
LONG count = _writeCount;
if( count == 1 ){
_InterlockedAnd( &_readCount, ~CAN_NOT_READ_SIGN );
SetEvent( _canReadEvent );
count = InterlockedDecrement( &_writeCount );
if( !count ){
return;
}
if( StopRead_WaitSetWrite() ){
return;
}
}else{
InterlockedDecrement( &_writeCount );
}
SetEvent( _canWriteEvent );
}

BOOL ReadWriteLock::StopRead_WaitSetWrite()
{
ResetEvent( _canReadEvent );
LONG count = _InterlockedOr( &_readCount, CAN_NOT_READ_SIGN );
if( count ){
_InterlockedOr( &_readCount, CAN_NOT_WRITE_SIGN );
count = InterlockedCompareExchange( &_readCount, CAN_NOT_READ_SIGN,
CAN_NOT_READ_SIGN | CAN_NOT_WRITE_SIGN );
if( count != (CAN_NOT_READ_SIGN | CAN_NOT_WRITE_SIGN) ){
return TRUE;
}
}
return FALSE;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息