本文提供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原子队列的更多相关文章

  1. c# 高效的线程安全队列ConcurrentQueue

    c#高效的线程安全队列ConcurrentQueue<T>(上) c# 高效的线程安全队列ConcurrentQueue(下) Segment类 c#高效的线程安全队列Concurrent ...

  2. c#高效的线程安全队列ConcurrentQueue<T>(上)

      ConcurrentQueue<T>队列是一个高效的线程安全的队列,是.Net Framework 4.0,System.Collections.Concurrent命名空间下的一个数 ...

  3. c# 高效的线程安全队列ConcurrentQueue(下) Segment类

    Segment成员变量 long long m_index; 记录该segment的索引号. int* volatile m_state; 状态数组,标识所对应的元素节点的状态,默认值为0,如果该元素 ...

  4. Git学习总结(5)——搭建Git简易高效服务器

    1. mysysgit+gitblit安装流程 1.1资源  需先下载好的资源(公司用的1.6,1.7+请自行匹配对应的mysysgit+gitblit):  jdk1.6  Git-1.8.4-pr ...

  5. 高效C++无锁队列实现-moodycamel::ConcurrentQueue

    国外一牛人做的,支持多平台,支持多线程写.多线程读,并可指定读写token,转载过来. 感觉作者也时刻维护着他这个项目,我提了一些问题,每次都会及时得到答复,而且回复得非常认真仔细,非常赞! 链接地址 ...

  6. Delphi 高效读写锁

    本人设计了一个高效读写锁,可实现多个线程读一个线程写的锁,应该比Delphi自带的读写锁高效,本人没有做对比测试. 本文的锁不可以在一个线程里重入,否则会锁死,另外读写锁最多支持65535个线程同时读 ...

  7. disruptor 高效队列

    disruptor 是什么: disruptor 是一个 低延时的 无锁 环形 队列.  相较于 java的 队列 ,他有明显的优点  ,无界,无锁,低延时(解决了为内存共享问题 ) disrupto ...

  8. [Java] 集合框架原理之二:锁、原子更新、线程池及并发集合

    java.util.concurrent 包是在 Java5 时加入的,与 concurrent 的相关的有 JMM及 AbstractQueuedSynchronizer (AQS),两者是实现 c ...

  9. XP局域网内专用消息队列

    网上能找到DELPHI消息队列的方法,在XP下试了总是不成功,后来在2003上试就行了,对比发现消息队列属性->安全 2003中多了个用户ANONYMOUS_LOGON. 然后在XP下消息队列属 ...

随机推荐

  1. Software Testing Techniques LAB 02: Selenium

    1. Installing 1. Install firefox 38.5.1 2. Install SeleniumIDE    After installing, I set the view o ...

  2. select server

    server with select #include<stdio.h> #include<sys/types.h> #include<sys/socket.h> ...

  3. auto_ptr与shared_ptr ZZ

    http://blog.csdn.net/rogeryi/article/details/1442700 Part(1) 这篇文章试图说明如何使用auto_ptr和shared_ptr,从而使得动态分 ...

  4. Java学习-0

    Java简单介绍 第一个程序Hello World 基本数据类型 对象和类 数据声明 函数声明 参数传递 Java简单介绍 Java的优点:简单.可移植性 JDK (Java Development ...

  5. Json转Map

    http = new HttpClient**();//此处封装一下发请求的类 Map<String, String> map = new HashMap<String, Strin ...

  6. iOS 滑动比较

    对iOS手机进行滑动操作进行总结:1.mobile:scroll向下滚动整个屏幕driver.execute_script('mobile: scroll', {'direction': 'down' ...

  7. Centos 7 iptables配置

    systemctl status firewalld.service #检测是否开启了firewall systemctl stop firewalld.service #关闭firewall syt ...

  8. SQL监控:mysql及mssql数据库SQL执行过程监控审计

    转载 Seay_法师 最近生活有很大的一个变动,所以博客也搁置了很长一段时间没写,好像写博客已经成了习惯,搁置一段时间就有那么点危机感,心里总觉得不自在.所以从今天起还是要继续拾起墨笔(键盘),继续好 ...

  9. [CTSC2018]假面

    题目 先来考虑一下第一问,血量有\(P\)的概率减\(1\) 由于我们最后需要求每一个人的期望血量,于是考虑维护出每个人处于不同血量时候的概率 一个简单\(dp\)即可 \[dp_{i,j}=dp_{ ...

  10. 【[NOI2009]管道取珠】

    --\(shallwe\):这道题是\(noipDay2T2\)难度 好一个\(Day2T2\)难度啊,我觉得我可以退役了 平方和好像没有什么办法可以快速统计,于是考虑转化一下 我们可以将题意转化成这 ...