简易高效的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下消息队列属 ...
随机推荐
- 在小程序中修改上一个页面里data中的数据调用上一个页面的方法
//获取已经打开的页面的数组 var pages = getCurrentPages(); //获取上一个页面的所有的方法和data中的数据 var lastpage = pages[pages.l ...
- iis7 未注册framework4 导致 莫名的404错误
server2008 R2 IIS7 已经安装 安装framework 4.6.1 然后建立站点 404错误 :在站点目录自动生成了 asp_client 重新注册到 iis(不需要) iisre ...
- January 09 2017 Week 2nd Monday
Patience is bitter, but its fruit is sweet. 忍耐是痛苦的,但它的果实是甜蜜的. Some patience may be just fruitless, o ...
- redis下的adlist
//adlist.h #ifndef __ADLIST__H__ #define __ADLIST__H__ typedef struct listNode_ { struct listNode_ * ...
- facebook开源的代码审核工具phabricator
主页地址:http://phabricator.org/
- PhoneGap 介绍
一.PhoneGap 是什么 1.PhoneGap 是一个用基于 HTML,CSS 和 JavaScript 的,创建移动跨平台移动应用程序的快速开发框架. 2.它使开发者能够利用 iPhone,An ...
- 操作dict时避免出现KeyError的几种方法
在读取dict的key和value时,如果key不存在,就会触发KeyError错误,如: Python t = { ', ', ', } print(t['d']) 就会出现: <code c ...
- Python中的类(一)
Python中的类(一) 一. 应用场景 如果多个函数中有一些相同的参数时,转换成面向对象. 二. 如何创建类 类是用来描述具有相同的属性和方法的对象的集合.它定义了该集合中每个对象所共有的属性和方法 ...
- C/C++——指针,引用做函数形参
函数中的形参是普通形参的时,函数只是操纵的实参的副本,而无法去修改实参. 引用形参是对实参的直接操纵,指针形参是对 它所指向的值(*p) 的直接操纵,但是对于这个指针变量(p)来说,依然只是副本. 指 ...
- programming-languages学习笔记--第7部分
programming-languages学习笔记–第7部分 */--> pre.src {background-color: #292b2e; color: #b2b2b2;} pre.src ...