一个可无限伸缩且无ABA问题的无锁队列
关于无锁队列,详细的介绍请参考陈硕先生的《无锁队列的实现》一文。然进一步,如何实现一个不限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问题的无锁队列的更多相关文章
- 无锁队列以及ABA问题
队列是我们非常常用的数据结构,用来提供数据的写入和读取功能,而且通常在不同线程之间作为数据通信的桥梁.不过在将无锁队列的算法之前,需要先了解一下CAS(compare and swap)的原理.由于多 ...
- 分享一个自己写的MVC+EF “增删改查” 无刷新分页程序
分享一个自己写的MVC+EF “增删改查” 无刷新分页程序 一.项目之前得添加几个组件artDialog.MVCPager.kindeditor-4.0.先上几个效果图. 1.首先建立一个数 ...
- readerwriterqueue 一个用 C++ 实现的快速无锁队列
https://www.oschina.net/translate/a-fast-lock-free-queue-for-cpp?cmp&p=2 A single-producer, sing ...
- boost 无锁队列
一哥们翻译的boost的无锁队列的官方文档 原文地址:http://blog.csdn.net/great3779/article/details/8765103 Boost_1_53_0终于迎来了久 ...
- CAS简介和无锁队列的实现
Q:CAS的实现 A:gcc提供了两个函数 bool __sync_bool_compare_and_swap (type *ptr, type oldval, type newval, ...)// ...
- 锁、CAS操作和无锁队列的实现
https://blog.csdn.net/yishizuofei/article/details/78353722 锁的机制 锁和人很像,有的人乐观,总会想到好的一方面,所以只要越努力,就会越幸运: ...
- zeromq源码分析笔记之无锁队列ypipe_t(3)
在上一篇中说到了mailbox_t的底层实际上使用了管道ypipe_t来存储命令.而ypipe_t实质上是一个无锁队列,其底层使用了yqueue_t队列,ypipe_t是对yueue_t的再包装,所以 ...
- 无锁队列--基于linuxkfifo实现
一直想写一个无锁队列,为了提高项目的背景效率. 有机会看到linux核心kfifo.h 原则. 所以这个实现自己仿照,眼下linux我们应该能够提供外部接口. #ifndef _NO_LOCK_QUE ...
- Go语言无锁队列组件的实现 (chan/interface/select)
1. 背景 go代码中要实现异步很简单,go funcName(). 但是进程需要控制协程数量在合理范围内,对应大批量任务可以使用"协程池 + 无锁队列"实现. 2. golang ...
随机推荐
- ASP.NET 网站在域环境内配置授权访问
在 IIS 中,通常需要配置域中的某些用户或者用户组有权限访问部署的 WEB 站点或者 WEB 服务.我们知道要实现这种功能可以有如下几种方式: 代码,获取当前用户,到域服务器上去验证当前用户是否为合 ...
- Ubuntu下Geary安装
sudo add-apt-repository ppa:yorba/ppasudo apt-get updatesudo apt-get install geary
- mysql insert和前台显示乱码
近期在搞服务端.遇到问题例如以下, 在mysql中插入中文乱码.或mysql中中文正常显示,但jsp在前台显示mysql中的中文时乱码. 解决方法,进入mysql控制台,运行 SET characte ...
- 把war包放到Tomcat安装文件夹下,不能直接訪问的解决方式
临床表现: Tomcat启动后首页能訪问(http://localhost:8080/). 将自己写的一个webprojectwar包放到Tomcat安装文件夹下的/webapps以下(比方hello ...
- Linux下patch打补丁命令
此命令用于为特定软件包打补丁,他使用diff命令对源文件进行操作. 基本命令语法: patch [-R] {-p(n)} [--dry-run] < patch_file_name p:为pat ...
- sql 去除结尾的回车或者换行
CREATE FUNCTION REMOVE_ENTER (@DESC VARCHAR(8000))RETURNS VARCHAR(8000)ASBEGIN DECLARE @STR VARCHAR( ...
- iOS极光推送的基本使用
昨天花了一下午的时间研究了下极光推送,也前也是没做过,不知道从何下手!才开始的时候一看官方的SDK感觉好难,不过经过一系列的捣鼓之后,手机收到了推送信息,感觉其实并没有那么难! 1.配置开发证书(得有 ...
- DEV控件自定义排序实现
一般的控件或者组件都支持按照某一列进行排序.但是,这种排序是根据数据源里的数据默认按照降序或升序排序的,同时这样的排序与字段的类型有关. 假设现在字段的类型是字符串类型 ,但是,存储的数据时数字加一些 ...
- fckeditor使用详解
FCKEditor是一个很好的用于Web页面中的格式化文本编译控件.现在越来越多的论坛的发帖页面中更多的使用了这个控件,我们这里将如何在基于Java的web开发中使用FCKEditor控件的步骤提供给 ...
- Android TextView文字超出一屏不能显示其它的文字 解决方案
在android上面让TextView 过多的文字实现有滚动条,之前想简单了以为设置TextView的属性就可以实现,结果还是需要ScrollView配合使用,才能达到滚动条的效果有两种方式实现, 一 ...