简易高效的Delphi原子队列
本文提供Delphi一个基于原子操作的无锁队列,简易高效。适用于多线程大吞吐量操作的队列。
可用于Android系统和32,64位Windows系统。
感谢歼10和qsl提供了修改建议!
有如下问题:
1.必须事先足够大开辟内存,大到不会出现队列溢出了。
2.队列大小必须是2的幂
3.不能压入空指针
4.本程序还未经过工程应用考验
unit Iocp.AtomQueue; interface Uses
SysUtils,
SyncObjs; Type
TAtomFIFO = Class
Protected
FWritePtr: Integer;
FReadPtr: Integer;
FCount:Integer;
FHighBound:Integer;
FisEmpty:Integer;
FData: array of Pointer;
function GetSize:Integer;
Public
procedure Push(Item: Pointer);
function Pop: Pointer;
Constructor Create(Size: Integer); Virtual;
Destructor Destroy; Override;
Procedure Empty;
property Size: Integer read GetSize;
property UsedCount:Integer read FCount;
End; Implementation //创建队列,大小必须是2的幂,需要开辟足够大的队列,防止队列溢出 Constructor TAtomFIFO.Create(Size: Integer);
var
i:NativeInt;
OK:Boolean;
Begin
Inherited Create;
OK:=(Size and (Size-)=); if not OK then raise Exception.Create('FIFO长度必须大于等于256并为2的幂'); try
SetLength(FData, Size);
FHighBound:=Size-;
except
Raise Exception.Create('FIFO申请内存失败');
end;
End; Destructor TAtomFIFO.Destroy;
Begin
SetLength(FData, );
Inherited;
End; procedure TAtomFIFO.Empty;
begin
while (TInterlocked.Exchange(FReadPtr, )<>) and
(TInterlocked.Exchange(FWritePtr, )<>) and
(TInterlocked.Exchange(FCount, )<>) do;
end; function TAtomFIFO.GetSize: Integer;
begin
Result:=FHighBound+;
end; procedure TAtomFIFO.Push(Item:Pointer);
var
N:Integer;
begin
if Item=nil then Exit; N:=TInterlocked.Increment(FWritePtr) and FHighBound;
FData[N]:=Item;
TInterlocked.Increment(FCount);
end; Function TAtomFIFO.Pop:Pointer;
var
N:Integer;
begin
if TInterlocked.Decrement(FCount)< then
begin
TInterlocked.Increment(FCount);
Result:=nil;
end
else
begin
N:=TInterlocked.Increment(FReadPtr) and FHighBound;
//假设线程A调用了Push,并且正好是第1个push,
//执行了N:=TInterlocked.Increment(FWritePtr) and FHighBound,
//还没执行FData[N]:=Item, 被切换到其他线程
//此时假设线程B调用了Push,并且正好是第2个push,并且执行完毕,这样出现FCount=1,第2个Item不为空,而第一个Item还是nil(线程A还没执行赋值)
//假设线程C执行Pop,由于Count>0(线程B的作用)所以可以执行到这里,但此时FData[N]=nil(线程A还没执行赋值),
//因此线程C要等待线程A完成FData[N]:=Item后,才能取走FData[N]
//出现这种情况的概率应该比较小,基本上不会浪费太多CPU
while FData[N]=nil do Sleep();
Result:=FData[N]; FData[N]:=nil;
end;
end; End.
性能测试:
采用天地弦提供的评估程序,进行了一些修改,分别对使用不同的临界区的队列进行对比结果如下:
其中Swith是因队列读空,进行线程上下文切换的次数

简易高效的Delphi原子队列的更多相关文章
- c# 高效的线程安全队列ConcurrentQueue
c#高效的线程安全队列ConcurrentQueue<T>(上) c# 高效的线程安全队列ConcurrentQueue(下) Segment类 c#高效的线程安全队列Concurrent ...
- c#高效的线程安全队列ConcurrentQueue<T>(上)
ConcurrentQueue<T>队列是一个高效的线程安全的队列,是.Net Framework 4.0,System.Collections.Concurrent命名空间下的一个数 ...
- c# 高效的线程安全队列ConcurrentQueue(下) Segment类
Segment成员变量 long long m_index; 记录该segment的索引号. int* volatile m_state; 状态数组,标识所对应的元素节点的状态,默认值为0,如果该元素 ...
- Git学习总结(5)——搭建Git简易高效服务器
1. mysysgit+gitblit安装流程 1.1资源 需先下载好的资源(公司用的1.6,1.7+请自行匹配对应的mysysgit+gitblit): jdk1.6 Git-1.8.4-pr ...
- 高效C++无锁队列实现-moodycamel::ConcurrentQueue
国外一牛人做的,支持多平台,支持多线程写.多线程读,并可指定读写token,转载过来. 感觉作者也时刻维护着他这个项目,我提了一些问题,每次都会及时得到答复,而且回复得非常认真仔细,非常赞! 链接地址 ...
- Delphi 高效读写锁
本人设计了一个高效读写锁,可实现多个线程读一个线程写的锁,应该比Delphi自带的读写锁高效,本人没有做对比测试. 本文的锁不可以在一个线程里重入,否则会锁死,另外读写锁最多支持65535个线程同时读 ...
- disruptor 高效队列
disruptor 是什么: disruptor 是一个 低延时的 无锁 环形 队列. 相较于 java的 队列 ,他有明显的优点 ,无界,无锁,低延时(解决了为内存共享问题 ) disrupto ...
- [Java] 集合框架原理之二:锁、原子更新、线程池及并发集合
java.util.concurrent 包是在 Java5 时加入的,与 concurrent 的相关的有 JMM及 AbstractQueuedSynchronizer (AQS),两者是实现 c ...
- XP局域网内专用消息队列
网上能找到DELPHI消息队列的方法,在XP下试了总是不成功,后来在2003上试就行了,对比发现消息队列属性->安全 2003中多了个用户ANONYMOUS_LOGON. 然后在XP下消息队列属 ...
随机推荐
- winform基础控件-例子学习
1.如图实现整数计算器 ComboBox控件: Items属性:添加集合中的项. this.comoper.Items.AddRange(new object[] { "+", & ...
- Linux yum提示Loaded plugins错误的解决方法
yum是Linux软件包管理器,也叫yum源,在yum使用过程中,有时会出现Loaded plugins错误,重启无效,遇到这种情况该如何解决呢?下面就给大家介绍下Linux yum提示Loaded ...
- MySQL Database on Azure服务在中国正式商用
基于由世纪互联运营的Windows Azure平台,MySQL Database on Azure服务助力中国用户实现数据库在云端的快速部署.推进用户的创新开发 2015年9月10日,北京——微软中国 ...
- 删除 maven仓库,更新失败的jar包命令
set REPOSITORY_PATH=D:\maven_cpbsrem صشعثرث÷...for /f "delims=" %%i in ('dir /b /s " ...
- laravel controller重写
<?php namespace Boss\Http\Controllers; use Illuminate\Foundation\Bus\DispatchesJobs; use Illumina ...
- PHP: APC Configuration and Usage Tips and Tricks
原文链接:http://www.if-not-true-then-false.com/2012/php-apc-configuration-and-usage-tips-and-tricks/3/ T ...
- vagrant 打造开发环境
1 vagrant http://www.vagrantup.com/ 2 veewee https://github.com/jedi4ever/veewee 3 vagrant boxes htt ...
- IOS .a静态库的和.framework制作
什么是库? 库是程序代码的集合,是共享程序代码的一种方式 根据源代码的公开情况,库可以分为2种类型 开源库 公开源代码,能看到具体实现 比如SDWebImage.AFNetworking 闭源库 不公 ...
- Linux系统下常用的磁盘管理命令——du / df / fdisk / mount / xxd
之前使用虚拟机体验Linux操作系统的使用,一般使用默认的磁盘分区设置,也很少涉及磁盘管理操作,且总有删除重装作为后盾.在安装Ubuntu双系统后,在使用过程中遇到了磁盘分区不合理导致的/boot分区 ...
- 弹框插件self(动效兼容到IE9,功能兼容IE6)
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...