本文提供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. 打印 1 到最大的 n 位数(C++ 和 Python 实现)

    (说明:本博客中的题目.题目详细说明及参考代码均摘自 “何海涛<剑指Offer:名企面试官精讲典型编程题>2012年”) 题目 输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数. ...

  2. npdp

    我报名比较晚,等缴费最后期限,才缴费,下定决心,开始正式的备考. 我的工作比较忙,备考时间特比较短,从拿到书到考试只有一个月了,心理慌慌的. 在岳老师的帮助下,完成了报名资格申请.拿到备考计划,就赶紧 ...

  3. awk 正则表达式、正则运算符详细介绍

    前言:使用awk作为文本处理工具,正则表达式是少不了的. 要掌握这个工具的正则表达式使用.其实,我们不必单独去学习它的正则表达式.正则表达式就像一门程序语言,有自己语法规则已经表示意思. 对于不同工具 ...

  4. Windows Server 2008 R2 /2012 修改密码策略(摘抄 原文地址 https://www.cnblogs.com/mili3/p/7799347.html)

    今天建了域环境,在添加新用户的时候,发现用简单的密码时域安全策略提示密码复杂度不够,于是我就想在域安全策略里面把密码复杂度降低一点. 问题:    在“管理工具 >> 本地安全策略 > ...

  5. iOS设计模式 - 外观

    iOS设计模式 - 外观 原理图 说明 1. 当客服端需要使用一个复杂的子系统(子系统之间关系错综复杂),但又不想和他们扯上关系时,我们需要单独的写出一个类来与子系统交互,隔离客户端与子系统之间的联系 ...

  6. CSV输入输出

    读取csv文件: import csv cf = open('D:\pywe.csv','rb') cf.readline() #读取标题行,光标移动到下一行(相当于调过标题行) for l in c ...

  7. Linux server配置安装Java,Tomcat服务器

    系统:Ubuntu 16.04 dev_desktop 1.Java安装并配置环境变量 (1)从Java官方网站下载最新版JDK: http://www.oracle.com/technetwork/ ...

  8. Linux sftp命令详解

    sftp是Secure File Transfer Protocol的缩写,安全文件传送协议.可以为传输文件提供一种安全的网络的加密方法.sftp 与 ftp 有着几乎一样的语法和功能.SFTP 为 ...

  9. ELK系统分析Nginx日志并对数据进行可视化展示

    结合之前写的一篇文章:ELK日志分析平台搭建全过程,上篇文章主要讲了部署方法.而这篇文章介绍的是单独监控nginx 日志分析再进行可视化图形展示. 本文环境与上一篇环境一样,前提 elasticsea ...

  10. 深入浅出SharePoint2013——常用术语

    CAS(Code Access Security)自定义代码访问安全性 Sandboxed solution 沙箱解决方案