关于无锁队列,详细的介绍请参考陈硕先生的《无锁队列的实现》一文。然进一步,如何实现一个不限node数目即能够无限伸缩的无锁队列,即是本文的要旨。

无锁队列有两种实现形式,分别是数组与链表。以数组实现的无锁队列,限定了基本node的数目,然没有ABA问题。以链表实现的无锁队列,在内存允许的情况下可以添加任意数目的node,然有ABA问题。如何取二者的优点而摒弃其各自的缺点呢?

如果要做到可以无限伸缩,那么这种无锁队列须采用链表实现,然如何解决ABA问题呢?

ABA问题的本质就是地址重用,即两个(或多个)访问者访问一个node,其中一个释放了这个node,此时os会回收这个node。然后另外一个访问者要新生成一个node时,os会把刚释放掉的那个node的内存空间分配给这个访问者。在这个过程中,如果我们不把释放掉的node还给os,是不是问题就解决了?

可保存需要释放的node而不还给os的技术,我能想到的是内存池。一个以链表形式实现的无锁队列使用它的内存池时,如果要对这个内存池加锁,那就不是无锁队列了。

这个内存池中每个node大小一致,用一个数组形式的无锁队列实现即可。本文需要的无锁队列便是用列表实现的,而且基于数组无锁队列内存池。

这里面还有一个问题。还是上面的那个场景,node被访问者释放后,此时由内存池保存着,然后另一个访问者要申请一个node的内存空间,便会向内存池申请,如果内存池是把那个刚被释放掉的node空间分配给它呢?相当于内存池替代了os,问题依然没有解决。

既然内存空间现在由内存池而非os管理着,哪我们就可以想办法解决了。

还是上面那个场景,如果内存池中有很多个node,队列形式的内存池还会把刚被释放掉的node空间分配出去吗?所以需要在内存池中保存多个node。但保存多少合适呢?保存的node数量大于等于同时向内存池申请node空间的访问者即可。

node的数量取决于访问者的数目,若访问者是线程,则这个数目就是就是写线程的数目,这个参数可以让使用者设置。为了编程方便,我假设线程池线程写线程最多不会超过2048个,这个值应该大于当前多数服务器中CPU数量。

我在64位linux上用C实现了本文讨论的无锁队列。请点击这里下载地址,还是老规矩,零分下载。

欢迎批评指正。

此记。

一个可无限伸缩且无ABA问题的无锁队列的更多相关文章

  1. 无锁队列以及ABA问题

    队列是我们非常常用的数据结构,用来提供数据的写入和读取功能,而且通常在不同线程之间作为数据通信的桥梁.不过在将无锁队列的算法之前,需要先了解一下CAS(compare and swap)的原理.由于多 ...

  2. 分享一个自己写的MVC+EF “增删改查” 无刷新分页程序

    分享一个自己写的MVC+EF “增删改查” 无刷新分页程序 一.项目之前得添加几个组件artDialog.MVCPager.kindeditor-4.0.先上几个效果图.      1.首先建立一个数 ...

  3. readerwriterqueue 一个用 C++ 实现的快速无锁队列

    https://www.oschina.net/translate/a-fast-lock-free-queue-for-cpp?cmp&p=2 A single-producer, sing ...

  4. boost 无锁队列

    一哥们翻译的boost的无锁队列的官方文档 原文地址:http://blog.csdn.net/great3779/article/details/8765103 Boost_1_53_0终于迎来了久 ...

  5. CAS简介和无锁队列的实现

    Q:CAS的实现 A:gcc提供了两个函数 bool __sync_bool_compare_and_swap (type *ptr, type oldval, type newval, ...)// ...

  6. 锁、CAS操作和无锁队列的实现

    https://blog.csdn.net/yishizuofei/article/details/78353722 锁的机制 锁和人很像,有的人乐观,总会想到好的一方面,所以只要越努力,就会越幸运: ...

  7. zeromq源码分析笔记之无锁队列ypipe_t(3)

    在上一篇中说到了mailbox_t的底层实际上使用了管道ypipe_t来存储命令.而ypipe_t实质上是一个无锁队列,其底层使用了yqueue_t队列,ypipe_t是对yueue_t的再包装,所以 ...

  8. 无锁队列--基于linuxkfifo实现

    一直想写一个无锁队列,为了提高项目的背景效率. 有机会看到linux核心kfifo.h 原则. 所以这个实现自己仿照,眼下linux我们应该能够提供外部接口. #ifndef _NO_LOCK_QUE ...

  9. Go语言无锁队列组件的实现 (chan/interface/select)

    1. 背景 go代码中要实现异步很简单,go funcName(). 但是进程需要控制协程数量在合理范围内,对应大批量任务可以使用"协程池 + 无锁队列"实现. 2. golang ...

随机推荐

  1. schema://host[:port#]/path/.../[?query-string][#anchor]

    1:http协议状态200 OK最常见的就是成功响应状态码200了, 这表明该请求被成功地完成,所请求的资源发送回客户端 302 Found重定向,新的URL会在response 中的Location ...

  2. [置顶] CSDN博客第三期云计算最佳博主评选

    CSDN博客第二期云计算最佳博主排行圆满结束,恭喜所有上榜用户,为继续展示云计算方向的优秀博主,发掘潜力新星,为云计算方向的博客用户提供平台,CSDN博客第三期云计算最佳博主排行开始.同时,获奖者有机 ...

  3. C++ 文件的复制、删除、重命名

    一.文件的复制 #include <iostream>#include <fstream>using namespace std; int CopyFile(char *Sou ...

  4. Spring、Hello AOP

    AOP 概念:http://blog.csdn.net/moreevan/article/details/11977115 AOP 所使用到的jar 包: aspectjrt.jar common-a ...

  5. 共享参数ContentProvider 类与数据库绑定,如何通过共享参数测试类,测试数据库的增删改查功能

    Intent可以传一个对象 当两个界面之间跳转时,需要传递一个对象过去,是通过使用Bundle类,并且实体类需要serializable实现序列化,传递方法如下: 定义一个静态常量作为key值 pub ...

  6. Haffman算法(C++)

    Huffman编码,C++实现,只是为了说明大致的思路,还有很多不完美之处,比如在输入数据超出限制等条件下会出现错误. #include<iostream> #include<str ...

  7. 蓝桥杯算法训练<一>

    一.图形显示 此题虽然简单,但是需啊哟注意的是,每个“*”后边有一个空格] 问题描述 编写一个程序,首先输入一个整数,例如5,然后在屏幕上显示如下的图形(5表示行数): * * * * * * * * ...

  8. 理解JS闭包

    从事web开发工作,尤其主要是做服务器端开发的,难免会对客户端语言JavaScript一些概念有些似懂非懂的,甚至仅停留在实现功能的层面上,接下来的文章,是记录我对JavaScript的一些概念的理解 ...

  9. 共享器 TS ERROR WINDOWS-FAILED 错误解决方法

    问题:TS  ERROR WINDOWS-FAILED 原因:微软操作系统自动更新补丁(KB956572)与终端机软件有冲突. 解决方法: .打开“开始菜单”: .打开“控制面板”: .打开“添加/删 ...

  10. doGet与doPost的区别

    转自:http://blog.csdn.net/luoweifu/article/details/7865243   目录(?)[-] 不同点一 不同点二 输入表单inputhtml Serlvlet ...