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 ...
随机推荐
- Software Testing Techniques Homework 1
I have met some errors in recent years, one of them which impress me most. It happend when I try to ...
- Oralce 序列
序列: 是oacle提供的用于产生一系列唯一数字的数据库对象. l 自动提供唯一的数值 l 共享对象 l 主要用于提供主键值 l 将序列值装入内存可以提高访问效率 创建序列: 1. 要有创建 ...
- leetcode Ch4-Binary Tree & BFS & Divide/Conquer
一. 1. Lowest Common Ancestor class Solution { public: TreeNode *lowestCommonAncestor(TreeNode *root, ...
- BufferedInputStream使用详解
下面的例子演示如何使用BufferedInputStream类读取文本文件内容. 首先需要声明一个byte数组作为buffer,然后循环将文本内容循环读入到buffer中,并将buffer转换为字符串 ...
- java 通过调用存储过程获取结果集
一般在java中,数据查询是通过Statement, PreparedStatement获取结果集,今天向大家介绍通过CallableStatement调用存储过程,从而获取结果集. 本 ...
- matlab中的knn函数
knn 最邻近分类 Class = knnclassify(test_data,train_data,train_label, k, distance, rule) k:选择最邻近的数量 distan ...
- Visual Studio Code (vscode)编译C++
Visual Studio Code (简称 VS Code / VSC) 是一款免费开源的现代化轻量级代码编辑器,支持几乎所有主流的开发语言的语法高亮.智能代码补全.自定义热键.括号匹配.代码片段. ...
- BZOJ 1191 超级英雄Hero 二分图匹配
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1191 题目大意: 现在电视台有一种节目叫做超级英雄,大概的流程就是每位选手到台上回答主 ...
- Android Studio 学习之 Android SDK快速更新
找到国内谷歌服务器IP地址 进入http://ping.chinaz.com/输入g.cn 然后查询出最快的节点,复制下IP地址.如:IP:203.208.40.146 响应时间:3毫秒 在Andr ...
- 第一篇markdown笔记
博客的样式设置 1 2 3 参考第一篇博客 参考第二篇博客 高效的写博客 博客园虽然支持markdown,但是好多快捷键都不支持,以后可以先在马克飞象上写好markdown笔记,再复制到博客上.