本文提供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. select 时进行update的操作,在高并发下引起死锁

    场景:当用户查看帖子详情时,把帖子的阅读量:ReadCount+1 select title,content,readcount from post where id='xxxx'   --根据主键查 ...

  2. 关于Angular中时间戳的计算

    前言 使用的是Moment.js 插件,插件的安装详情请参考官方网址(https://momentjs.com/) 正文 步骤一:引用import * as moment from 'moment'; ...

  3. 辉光的UIView

    辉光的UIView 辉光UIView使用了一个UIView的一个category,名为UIView+Glow,请自行到github上查找. 源码如下: // // RootViewController ...

  4. [翻译] TWRPickerSlider

    TWRPickerSlider https://github.com/chasseurmic/TWRPickerSlider Usage Add the dependency to your Podf ...

  5. Using shared access signatures (SAS) From Microsoft

    A shared access signature (SAS) provides you with a way to grant limited access to objects in your s ...

  6. Linux命令--权限管理

    chmod命令 Linux/Unix 的文件调用权限分为三级 : 文件拥有者.群组.其他.利用 chmod 可以藉以控制文件如何被他人所调用. 使用权限 : 所有使用者 语法 chmod [-cfvR ...

  7. Foj 2296 Alice and Bob(博弈、搜索)

    Foj 2296 Alice and Bob 题意 两个人博弈,规则如下:轮流取0~9中的数字,最后Alice所得的数字个数为1~n中,数位在Alice所取集合中出现奇数次的. 双方想获得尽量多,问A ...

  8. [零基础学JAVA]Java SE面向对象部分.面向对象基础(06)

    1.interface 接口 2.设计模式(工厂模式) 3.异常的捕获 java: //接口中定义的全是public,即使不声明也是public的,//如果一个类定义的时候全部由抽象方法和全局常量所组 ...

  9. J2EE项目异常处理(转)

     为什么要在J2EE项目中谈异常处理呢?可能许多java初学者都想说:“异常处理不就是try….catch…finally吗?这谁都会啊!”.笔者在初学java时也是这样认为的.如何在一个多层的j2e ...

  10. 劳动节前得空半天-总结一下最近使用的LINUX命令

    一.搜索文件 1.locate xxx.log   全盘搜索xxx.log文件 2.which java       查找命令 3.ll  xxx.log         在目录下查找文件 二.搜索内 ...