一不留神实现了一个特轻量级的多读单写锁?

阿呆_ 2009-09-11 08:51:35
加精
除了不支持嵌套似乎没什么逻辑问题. 代码中使用了Sleep(1)而没有使用Sleep(0)或SwitchToThread()是为了保证当前等待的线程将执行控制权切换到其它正处理锁定数据的线程--即使它线程优先级低也能切换,并且避免由于多次调用Sleep(0)或SwithThread而带来的当前线程执行时间片过少而使内核自动升级当前线程优先级而造成长时间执行无效代码。


var
iLock: Integer;

procedure ReadLock;
begin
while InterlockedIncrement(iLock) <= 0 do
begin
InterlockedDecrement(iLock);
Sleep(1);
end;
end;

procedure ReadUnlock;
begin
InterlockedDecrement(iLock);
end;

procedure WriteLock;
begin
while (InterlockedCompareExchange(iLock, $FF000000, 0) <> 0) do
Sleep(1);
end;

procedure WriteUnlock;
begin
InterlockedExchange(iLock, -1);
InterlockedIncrement(iLock);
end;
...全文
3227 139 打赏 收藏 转发到动态 举报
写回复
用AI写文章
139 条回复
切换为时间正序
请发表友善的回复…
发表回复
HeShe 2009-09-18
  • 打赏
  • 举报
回复
使用sleep的思路不好,本来似乎是为了简单,最后要让你陷入窘境。

貌似实现读写锁的功能,性能上却一点不轻量,多核上很沉重,你说特轻可能是觉得代码短吧。
yuanstudy 2009-09-16
  • 打赏
  • 举报
回复
很多不懂,才更要学习,收藏慢慢学习
acdb234 2009-09-16
  • 打赏
  • 举报
回复
初来混的,什么也看不懂,希望能学点什么
wish_cn 2009-09-16
  • 打赏
  • 举报
回复
加点代码是可以实现嵌套的。重点是InterlockedCompareExchange, 也就是x86的CMPXCHG指令。
laibach0304 2009-09-15
  • 打赏
  • 举报
回复
用sleep了,肯定好不了,sleep这个函数基本是没用的,还不如select
pao810 2009-09-15
  • 打赏
  • 举报
回复
dddddddddddddddddddddddddddd
anydeng 2009-09-15
  • 打赏
  • 举报
回复
观摩观摩。等遇到锁问题时再来细细研究。
yc_8301 2009-09-15
  • 打赏
  • 举报
回复
mark
husion01 2009-09-15
  • 打赏
  • 举报
回复
路过
z165397982 2009-09-15
  • 打赏
  • 举报
回复
赚分,,走人..!!
windy1234 2009-09-15
  • 打赏
  • 举报
回复
仔细研究一下
EssenChen 2009-09-15
  • 打赏
  • 举报
回复
Mark
zbkiller 2009-09-14
  • 打赏
  • 举报
回复
.... ...
zhaoweiting0609 2009-09-14
  • 打赏
  • 举报
回复
mark下,有时间了研究
zhaoxialx 2009-09-14
  • 打赏
  • 举报
回复
Fighting~
cchaha 2009-09-14
  • 打赏
  • 举报
回复
有JAVA版本的吗
reneeland 2009-09-14
  • 打赏
  • 举报
回复
mark!
很土 2009-09-14
  • 打赏
  • 举报
回复
TKYLockRW类是使用C++写的,没有任何难点就可直接转换成Delphi类,不过要真正明白TKYLockRW类倒不是一件容易的事情。

class TKYLockRW
{
public:
TKYLockRW();
virtual ~TKYLockRW();

bool LockRead();
bool LockWrite();

bool TryLockRead();
bool TryLockWrite();

void UnlockRead();
void UnlockWrite();

private:
void Lock() { EnterCriticalSection(&FRWLock); }
void Unlock() { LeaveCriticalSection(&FRWLock); }

inline void SetReadSignal();
inline void SetWriteSignal();

private:
CRITICAL_SECTION FRWLock;
HANDLE FReaderEvent;
HANDLE FWriterEvent;
long FReadingCount;
long FWritingCount;
long FWaitingReadCount;
long FWaitingWriteCount;
};

// ---------------- 构造函数和析构函数 ----------------
// 构造函数
TKYLockRW::TKYLockRW()
{
// 初始化
FReadingCount = 0;
FWritingCount = 0;
FWaitingReadCount = 0;
FWaitingWriteCount= 0;

// 创建临界区和读写者事件
InitializeCriticalSection(&FRWLock);
FReaderEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
FWriterEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
}

// 析构函数
TKYLockRW::~TKYLockRW()
{
// 置释放标志
Lock();
bool bWaiting = (FReadingCount > 0) || (FWritingCount == 1)
|| (FWaitingReadCount > 0)
|| (FWaitingWriteCount > 0);
FReadingCount = -1;
Unlock();

// 等待一会儿
if (bWaiting)
Sleep(10);

// 释放临界区和读写者事件
CloseHandle(FReaderEvent);
CloseHandle(FWriterEvent);
DeleteCriticalSection(&FRWLock);
}

// ---------------- 私有方法 ----------------
// 设置读信号
inline void TKYLockRW::SetReadSignal()
{
// FWritingCount 作为读信号广播的个数
if (FWritingCount == 0)
FWritingCount = -FWaitingReadCount;

// 是否需要继续广播
if (FWritingCount < 0)
{
FWritingCount++;
FReadingCount++;
FWaitingReadCount--;

SetEvent(FReaderEvent);
}
}

// 设置写信号
inline void TKYLockRW::SetWriteSignal()
{
FWritingCount = 1;
FWaitingWriteCount--;

SetEvent(FWriterEvent);
}

// ---------------- 公有方法 ----------------
// 读加锁
bool TKYLockRW::LockRead()
{
bool result = true;
bool bWaiting = false;

// 读数加 1
Lock();
if (FReadingCount == -1) // 释放标志
result = false;
else if ((FWritingCount == 1) || (FWaitingWriteCount > 0))
{
FWaitingReadCount++;
bWaiting = true;
}
else
FReadingCount++;
Unlock();

// 判断是否等待读信号
if (bWaiting)
{
// 等待读信号
result = (WaitForSingleObject(FReaderEvent, INFINITE) == WAIT_OBJECT_0);

if (result)
{
// 若广播个数不为零则继续置信号
Lock();
if (FWritingCount < 0)
SetReadSignal();
Unlock();
}
}

// 返回结果
return result;
}

// 写加锁
bool TKYLockRW::LockWrite()
{
bool result = true;
bool bWaiting = false;

// 写数置 1
Lock();
if (FReadingCount == -1) // 释放标志
result = false;
else if ((FWritingCount == 1) || (FReadingCount > 0))
{
FWaitingWriteCount++;
bWaiting = true;
}
else
FWritingCount = 1;
Unlock();

// 判断是否等待写信号
if (bWaiting)
result = (WaitForSingleObject(FWriterEvent, INFINITE) == WAIT_OBJECT_0);

// 返回结果
return result;
}

// 读试着加锁
bool TKYLockRW::TryLockRead()
{
bool result = true;

// 读数加 1
Lock();
if ((FReadingCount == -1) || (FWritingCount == 1)
|| (FWaitingWriteCount > 0))
result = false;
else
FReadingCount++;
Unlock();

// 返回结果
return result;
}

// 写试着加锁
bool TKYLockRW::TryLockWrite()
{
bool result = true;

// 写数置 1
Lock();
if ((FReadingCount == -1) || (FWritingCount == 1)
|| (FReadingCount > 0))
result = false;
else
FWritingCount = 1;
Unlock();

// 返回结果
return result;
}

// 读解锁
void TKYLockRW::UnlockRead()
{
Lock();
if (FReadingCount > 0)
{
// 读数减 1
FReadingCount--;

// 置读/写信号
if (FReadingCount == 0)
{
if (FWaitingWriteCount > 0)
SetWriteSignal();
else
SetReadSignal();
}
}
Unlock();
}

// 写解锁
void TKYLockRW::UnlockWrite()
{
Lock();
if (FWritingCount == 1)
{
// 写数置 0
FWritingCount = 0;

// 置读/写信号
if (FWaitingWriteCount > FWaitingReadCount)
SetWriteSignal();
else
SetReadSignal();
}
Unlock();
}
JavaMengJianjun 2009-09-14
  • 打赏
  • 举报
回复
Up
dinoalex 2009-09-14
  • 打赏
  • 举报
回复
[Quote=引用 109 楼 kyee 的回复:]
多读单写锁原码:http://blog.csdn.net/kyee/archive/2009/03/30/4037116.aspx

只能在一个进程中使用,不能跨进程。
[/Quote]

你怎么不发一下呢?
加载更多回复(116)

1,183

社区成员

发帖
与我相关
我的任务
社区描述
Delphi Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧