可用于进程间共享的超小型多读单写锁
来源:互联网 发布:数据备份与还原 编辑:程序博客网 时间:2024/03/29 09:15
使用起来极其简单, 任何初始值为0的Integer变量都可以作为锁变量, 通过BeginRead(), EndRead(), BeginWrite(), EndWrite()来同步共享资源的读写操作, 如果作为锁变量的Integer位于进程间的共享内存(比如FileMapping)中, 那么就可以实现进程间访问共享数据的同步. 功能和微软的SRW(Slim Reader/Writer) Locks相似, 不过比它强的是支持任意锁嵌套.
需要注意的一点: 读锁升级写锁过程中数据可能被其它先一步加写锁成功的线程修改, 即BeginRead()后, 调用BeginWrite()前和调用BeginWrite()后数据可能已经发生变化.
源码如下:
需要注意的一点: 读锁升级写锁过程中数据可能被其它先一步加写锁成功的线程修改, 即BeginRead()后, 调用BeginWrite()前和调用BeginWrite()后数据可能已经发生变化.
源码如下:
unit uSimplestRWLock;interfaceuses Windows, SysUtils; procedure BeginRead(var iLock: Integer); procedure EndRead(var iLock: Integer); procedure BeginWrite(var iLock: Integer); procedure EndWrite(var iLock: Integer);implementationtype PThrdLckInfo = ^TThrdLckInfo; TThrdLckInfo = record Ident: Pointer; iRCnt: Integer; iWCnt: Integer; Prev, Next: PThrdLckInfo; end;threadvar iInfo: PThrdLckInfo;{ Coz InterlockedCompareExchange differs in d7 and d200x, define ourselves here }function InterlockedCompareExchange(var Destination: Integer; Exchange: Integer; Comperand: Integer): Integer stdcall; external kernel32 name 'InterlockedCompareExchange';function GetLckInfo(p: Pointer): PThrdLckInfo;begin Result := iInfo; while (Result <> nil) and (Result.Ident <> p) do Result := Result.Next; if Result = nil then begin Result := PThrdLckInfo(AllocMem(sizeof(TThrdLckInfo))); Result.Next := iInfo; iInfo := Result; Result.Ident := p; end;end;procedure FreeInfo(p: PThrdLckInfo);begin if p.Prev <> nil then p.Prev.Next := p.Next; if p.Next <> nil then p.Next.Prev := p.Prev; if iInfo = p then iInfo := p.Next; FreeMem(p);end;const MAX_LIGHTWEIGHT_SWITCH = 5; MAX_MEDIUMWEIGHT_SWITCH = 10; HEAVYWEIGHT_SWITCH_INTERVAL = 50;procedure SwitchOut(var Cnt: Integer); // wait functionbegin if Cnt < MAX_LIGHTWEIGHT_SWITCH then begin Inc(Cnt); if SwitchToThread then Exit; end; if Cnt < MAX_MEDIUMWEIGHT_SWITCH then begin Inc(Cnt); Sleep(1); Exit; end; Cnt := 0; WaitForSingleObject(GetCurrentThread, HEAVYWEIGHT_SWITCH_INTERVAL);end;procedure BeginRead(var iLock: Integer); // iLock = 0: none lock // > 0: someone has locked for writing // < 0: someone has locked for readingvar n, c: Integer; p: PThrdLckInfo;begin p := GetLckInfo(@iLock); if p.iRCnt < 0 then // recursively reader lock Dec(p.iRCnt) else if p.iWCnt > 0 then // writer lock already applied begin InterlockedDecrement(iLock); Dec(p.iRCnt); end else begin // try to lock for reading, if iLock <= 0 then can be locked // otherwise must wait for writer-lock to unlock c := 0; repeat n := InterlockedCompareExchange(iLock, 0, 0); if (n > 0) then // other thread has locked for writing begin SwitchOut(c); // wait Continue; end; until InterlockedCompareExchange(iLock, n-1, n) = n; // iLock := iLock-1 if succeeded Dec(p.iRCnt); end;end;procedure EndRead(var iLock: Integer);var p: PThrdLckInfo;begin p :=GetLckInfo(@iLock); if InterlockedIncrement(p.iRCnt) = 0 then // current thread's last reader lock begin InterlockedIncrement(iLock); SwitchToThread; // give other waiting threads a chance to acquire their locks end; if (p.iRCnt = 0) and (p.iWCnt = 0) then FreeInfo(p);end;procedure BeginWrite(var iLock: Integer);var n, v, c: Integer; p: PThrdLckInfo;begin p := GetLckInfo(@iLock); c := 0; if p.iWCnt > 0 then // already locked for writing Inc(p.iWCnt) else begin v := GetCurrentThreadId shl 1; if p.iRCnt < 0 then // has previous reader lock begin InterlockedIncrement(iLock); // temporarily unlock reader Dec(v); end; repeat n := InterlockedCompareExchange(iLock, v, 0); // succeed only none has locked if n <> 0 then SwitchOut(c); until n = 0; Inc(p.iWCnt); end;end;procedure EndWrite(var iLock: Integer);var n, v: Integer; p: PThrdLckInfo;begin p := GetLckInfo(@iLock); if InterlockedDecrement(p.iWCnt) = 0 then // current thread's last writer lock begin v := GetCurrentThreadId shl 1; repeat n := iLock; until InterlockedCompareExchange(iLock, n-v, n) = n; // if succeeded, iLock is 0 (none lock) // or -1 (it's an upgraded writer lock, // reader lock still exists) if (p.iRCnt = 0) and (p.iWCnt = 0) then FreeInfo(p); SwitchToThread; end;end;end.
- 可用于进程间共享的超小型多读单写锁
- UDP广播(可用于本机进程间通信)
- 内存体系 用共享段于进程间联系
- 查看linux被隐藏进程的内存占用方法,可用于监控进程是否内存泄漏
- 超小型局域网组建的方案
- 进程间的数据共享
- 进程间共享的 变量
- 进程间的共享内存
- 没有可用于当前位置的源代码
- 没有可用于当前位置的源代码
- 可用于J2ME的GZip算法包
- 没有可用于当前位置的源代码
- EMCV,可用于DSP的OpenCV
- 没有可用于当前位置的源代码
- 可用于权限计算的帮助类
- 没有可用于当前位置的源代码
- vs2008"没有可用于当前位置的源代码"
- 没有可用于当前位置的源代码
- SDK兼容性的代码
- C#接口零度学习
- ObjC: 源文件的组织
- JDK 文档之 -- OutputStream 和 InputStream 的区别
- python rabittmq
- 可用于进程间共享的超小型多读单写锁
- 图的Flord算法(图中点到点的最短距离
- 解决 死锁 问题
- SQL SERVER做除法四舍五入
- Android之传感器系统(Gsensor)
- Labview机器视觉(6)-图像识别
- 让你提升命令行效率的 Bash 快捷键 [完整版]
- MySQL Query Cache 小结
- Silverlight 利用Telerik导出到Word