Delphi 高效读写锁
本人设计了一个高效读写锁,可实现多个线程读一个线程写的锁,应该比Delphi自带的读写锁高效,本人没有做对比测试。
本文的锁不可以在一个线程里重入,否则会锁死,另外读写锁最多支持65535个线程同时读。
// HeZiHang@cnblogs
// 跨平台简易高效锁 unit utLocker; interface type
// 多读单写锁
// 1.写的时候阻塞其他所有写和读
// 2.读的时候不阻塞其他读,但阻塞所有写,当阻塞了一个或以上的写后,将阻塞所有后来新的读
TMultiReadSingleWriteLocker = class
protected
[Volatile]
FLocker: Integer;
public
procedure LockRead;
procedure UnLockRead; inline;
procedure LockWrite;
procedure UnLockWrite; inline;
function TryLockRead: Boolean; inline;
function TryLockWrite: Boolean; inline;
constructor Create;
end; TSimpleLocker = class
protected
[Volatile]
FLocker: Integer;
public
procedure Lock;
procedure UnLock; inline;
function TryLock: Boolean; inline;
end; implementation uses System.SyncObjs, System.SysUtils, System.Classes; type
TSpinWait = record
private const
YieldThreshold = 10;
Sleep1Threshold = 20;
Sleep0Threshold = 5;
private
FCount: Integer;
function GetNextSpinCycleWillYield: Boolean; inline;
public
procedure Reset;inline;
procedure SpinCycle;inline; property Count: Integer read FCount;
property NextSpinCycleWillYield: Boolean read GetNextSpinCycleWillYield;
end; { TSpinWait } function TSpinWait.GetNextSpinCycleWillYield: Boolean;
begin
Result := (FCount > YieldThreshold) or (CPUCount = 1);
end; procedure TSpinWait.Reset;
begin
FCount := 0;
end; procedure TSpinWait.SpinCycle;
var
SpinCount: Integer;
begin
if NextSpinCycleWillYield then
begin
if FCount >= YieldThreshold then
SpinCount := FCount - YieldThreshold
else
SpinCount := FCount;
if SpinCount mod Sleep1Threshold = Sleep1Threshold - 1 then
TThread.Sleep(1)
else if SpinCount mod Sleep0Threshold = Sleep0Threshold - 1 then
TThread.Sleep(0)
else
TThread.Yield;
end
else
TThread.SpinWait(4 shl FCount);
Inc(FCount);
if FCount < 0 then
FCount := YieldThreshold + 1;
end; { TMultiReadSingleWriteLocker } procedure TMultiReadSingleWriteLocker.LockRead;
var
CurLock: Integer;
Wait: TSpinWait;
begin
Wait.Reset;
while True do
begin
CurLock := FLocker;
if CurLock <= $FFFF then
begin
if TInterlocked.CompareExchange(FLocker, CurLock + 1, CurLock) = CurLock
then
Exit;
end;
Wait.SpinCycle;
end;
end; procedure TMultiReadSingleWriteLocker.LockWrite;
var
CurLock: Integer;
Wait: TSpinWait;
begin
Wait.Reset;
while True do
begin
CurLock := FLocker;
if CurLock <= $FFFF then
begin
if TInterlocked.CompareExchange(FLocker, CurLock + $10000, CurLock) = CurLock
then
Exit;
end;
Wait.SpinCycle;
end;
end; function TMultiReadSingleWriteLocker.TryLockRead: Boolean;
var
CurLock: Integer;
begin
CurLock := FLocker;
if CurLock <= $FFFF then
Result := TInterlocked.CompareExchange(FLocker, CurLock + 1, CurLock)
= CurLock
else
Result := False;
end; function TMultiReadSingleWriteLocker.TryLockWrite: Boolean;
var
CurLock: Integer;
begin
CurLock := FLocker;
if CurLock <= $FFFF then
Result := TInterlocked.CompareExchange(FLocker, CurLock + $10000, CurLock)
= CurLock
else
Result := False;
end; procedure TMultiReadSingleWriteLocker.UnLockWrite;
begin
if FLocker < $10000 then
raise Exception.Create('TMultiReadSingleWriteLocker Error'); TInterlocked.Add(FLocker, -$10000);
end; procedure TMultiReadSingleWriteLocker.UnLockRead;
begin
TInterlocked.Decrement(FLocker);
end; constructor TMultiReadSingleWriteLocker.Create;
begin
FLocker := 0;
end; { TSimpleLocker } procedure TSimpleLocker.Lock;
var
Wait: TSpinWait;
begin
Wait.Reset;
while True do
begin
if FLocker = 0 then
begin
if TInterlocked.CompareExchange(FLocker, 1, 0) = 0 then
Exit;
end;
Wait.SpinCycle;
end;
end; function TSimpleLocker.TryLock: Boolean;
begin
if FLocker = 0 then
begin
Result := TInterlocked.CompareExchange(FLocker, 1, 0) = 0;
end
else
Result := False;
end; procedure TSimpleLocker.UnLock;
begin
if TInterlocked.CompareExchange(FLocker, 0, 1) <> 1 then
raise Exception.Create('TSimpleLocker Error');
end; end.
Delphi 高效读写锁的更多相关文章
- 技术笔记:Delphi多线程应用读写锁
在多线程应用中锁是一个很简单又很复杂的技术,之所以要用到锁是因为在多进程/线程环境下,一段代码可能会被同时访问到,如果这段代码涉及到了共享资源(数据)就需要保证数据的正确性.也就是所谓的线程安全.之前 ...
- ReentrantReadWriteLock 读写锁解析
4 java中锁是个很重要的概念,当然这里的前提是你会涉及并发编程. 除了语言提供的锁关键字 synchronized和volatile之外,jdk还有其他多种实用的锁. 不过这些锁大多都是基于AQS ...
- JAVA锁机制-可重入锁,可中断锁,公平锁,读写锁,自旋锁,
如果需要查看具体的synchronized和lock的实现原理,请参考:解决多线程安全问题-无非两个方法synchronized和lock 具体原理(百度) 在并发编程中,经常遇到多个线程访问同一个 ...
- Java并发(8)- 读写锁中的性能之王:StampedLock
在上一篇<你真的懂ReentrantReadWriteLock吗?>中我给大家留了一个引子,一个更高效同时可以避免写饥饿的读写锁---StampedLock.StampedLock实现了不 ...
- golang互斥锁和读写锁
一.互斥锁 互斥锁是传统的并发程序对共享资源进行访问控制的主要手段.它由标准库代码包sync中的Mutex结构体类型代表.sync.Mutex类型(确切地说,是*sync.Mutex类型)只有两个公开 ...
- Go 互斥锁(sync.Mutex)和 读写锁(sync.RWMutex)
什么时候需要用到锁? 当程序中就一个线程的时候,是不需要加锁的,但是通常实际的代码不会只是单线程,所以这个时候就需要用到锁了,那么关于锁的使用场景主要涉及到哪些呢? 多个线程在读相同的数据时 多个线程 ...
- 【漫画】互斥锁ReentrantLock不好用?试试读写锁ReadWriteLock
ReentrantLock完美实现了互斥,完美解决了并发问题.但是却意外发现它对于读多写少的场景效率实在不行.此时ReentrantReadWriteLock来救场了!一种适用于读多写少场景的锁,可以 ...
- 从自旋锁、睡眠锁、读写锁到 Linux RCU 机制讲解
同步自我的 csdn 博客 6.S081 从自旋锁.睡眠锁.读写锁到 Linux RCU 机制讲解_我说我谁呢 --CSDN博客 总结一下 O/S 课程里面和锁相关的内容. 本文是 6.S0 ...
- java多线程-读写锁
Java5 在 java.util.concurrent 包中已经包含了读写锁.尽管如此,我们还是应该了解其实现背后的原理. 读/写锁的 Java 实现(Read / Write Lock Java ...
随机推荐
- js 图形化工作流设计器
最近比较闲,打算开发一个用js 写的 图形化工作流设计器,附上草图一张,要看运行效果请下载附件,这个版本还在开发中,以后会持续更新,直到满意为止.上面的列子虽然变形,我还是贴出来了,给大家一个 ...
- 打通版微社区(2):服务器部署MySql数据库 For DZ3.2
写在前面:单独写部署MySql原因是,我这边的应用数据库都是独立存在的,数据与应用分别部署在不同的服务器.另外我也没有实际部署MySql的经验,特意写一篇日志,张记性.安装MySql参考了http:/ ...
- linux 下MySQL的安装
一.安装MySQL 1.下载源码包 从mysql官网上下载linux下的source包mysql-5.0.51b.tar.gz,注意是下载GNU tar格式的,不是rpm包. 2.解 ...
- 详解COM Add In的LoadBehavior及其妙用
Office的所有COM Add In,包括用Shared Add In模板和VSTO Add In模板创建的,都会在注册表里面存储一些信息. 对于当前用户安装的Add In,以Excel为例,对应 ...
- 深入探索C++对象模型(1) 关于对象(思维导图)
通过上面整个关于对象的基础知识框架,我们来分析两个例子,看一下在内存中,对象究竟长什么样. Demo1:C++对象模型的内存布局 class Point { public: Point( floa ...
- Python实例---基于页面的后台管理[简单版]
后台管理菜单 + 母板[css/content/js] 向后台提交数据[2种]: 1. 模态对话框(数据少操作,且Js复杂): form表单 :优点:简单,前端提交后后台处 ...
- 连续支付的年金(continuously payable annuity)
一.含义 假设连续不断地付款,但每年的付款总量仍然为1元. 二. 连续支付年金是年支付次数m趋于无穷大时的年金,故 连续支付年金与基本年金的关系: 连续支付,每年的支付总量为1,支付期限为无穷: 积累 ...
- iOS开发之iOS界面UI
1.UILabel NSString *str = @"字符串大小"; UIFont *font = [UIFont fontWithName:@"Arial" ...
- python 脚本运行时报错: AttributeError: 'module' object has no attribute ***
最近在编写Python脚本过程中遇到一个问题比较奇怪:Python脚本完全正常没问题,但执行总报错"AttributeError: 'module' object has no attrib ...
- poi导出excel出现本工作薄不能再使用其他新字体的解决方法
最近使用POI处理EXCEL,当处理的单元格太多时,就会出现,本工作薄使用字体过多,不能再使用其他新的字体的是提示. 网上很多方法告诉我,要怎么修改excel文件,但是这个解决不了问题啊,难道让客户去 ...