分布式与多核处理器在共享资源的情况下均要求在线程安全完成提交的任务,在多线程并发处理大量数据任务情况下为解决多生产者多消费者保证任务队列线程安全设计查找到一种高性能无锁队列设计,进行学习、研究。

主要问题—资源竞争

一个通用的无锁队列似乎相当容易实现。问题的根源在于相同的变量必然需要与多个线程共享。例如,采取一种基于链表的通用方法:至少需要共享列表的头部和尾部,因为消费者都需要能够读取和更新头部,而生产者都需要能够更新尾部。当多个线程需要更新队列但要求保持队列处于一致的状态下肯定会导致资源分互斥访问。例如,如果消费者从队列中读取最后一个任务节点并仅更新头部,尾指针不应该指向它,因为该任务节点很快就会被释放。但是消费者可能被操作系统打断,在更新尾部之前暂停几毫秒,在这段时间内,尾指针可以被另一个生产者更新,然后第一个消费者将其设置为null就太晚了。

解决共享数据安全访问是无锁编程的关键。通常最好的方法是设想一种算法,它不需要首先更新多个变量以保持一致性,或者增量更新仍然使数据结构保持一致状态。不同的技巧可以使用,如在指针的最后两位存储额外的状态,指针和引用计数等,但像这些方法只能越走越远,真正的解决办法是开发算法本身。

设计思路

更少的线程在相同的数据上进行斗争,必然降低开销。因此,不能使用一个单一的数据结构,进行所有的操作。如果每一个生产者线程对应一个队列,这意味着不同的线程是完全平行的,彼此独立。

当然,消费者获取任务稍微复杂一些,任务出队时我们必须检查每个任务队列。从不同队列中获取任务的顺序并不重要,而同一生产者产生的任务的相对顺序至始至终是一致的,尽管任务队列之间获取任务的相对顺序可能交错,但并无不可,因为即使在单队列模型中,不同生产者产生的任务入队的顺序也是不确定的(因为不同生产者之间有一个竞争条件)。这种方法的唯一缺点是,如果队列是空的,必须检查每个子队列以确定这一点(同时,在检查一个子队列的时候,以前空的队列可能已经变成非空),但实际上这不会造成问题。在非空的情况下,由于子队列可以与消费者“配对”,所以总体上的争用更少,数据共享达到接近最优的水平(每个消费者都与一个生产者匹配),这个“配对”是使用一种启发式的方法,必须在任务出队期间保持某种状态——这是通过用户指定的“令牌”来完成的。注意,令牌是完全可选的——队列只返回到搜索每个队列中任务,只是在涉及多个线程时稍微慢一点。

每个队列中使用的核心算法不是基于节点链表(这意味着不断地分配和释放或重用元素,并且通常依赖于一个比较和交换的循环,在激烈的争用过程中可能会比较慢),每个队列基于数组模型,没有链接单个元素,而是多个元素一个“块”。队列的逻辑头指针和尾指针使用原子递增的整数表示。在这些逻辑指针和“块”之间,存在一个将每个指针映射到该块中索引的方案。入队操作只是增加了尾部标记(每个子队列只有一个生产者线程)。出队操作增加了头部标记,如果头部小于尾部,然后检查是否意外地增加了头尾的头部(这可能发生在争用的情况下——每个子队列有多个消费线程)。如果头部超过了尾部,那么就会增加一个校正计数器(使队列最终保持一致),如果不增加,它就会继续前进,并增加另一个整数,从而使它成为实际的最终逻辑索引。这个最终索引的增量总是在实际队列中生成一个有效的索引,不管其他线程在做什么或已经做了什么。这是有效的,因为只有当保证至少有一个元素被删除时,最终索引才会增加(当第一个索引被增加时,它会被检查)。

入队操作是通过单个原子增量完成的,而一个出队是快速地完成两个原子增量。当然,这需要对所有块分配、重用、引用计数、块映射的实现,这一点很重要,大多数的成本分摊到“块”上。这个设计允许极其高效的批量操作——原子的指令(这往往是一个瓶颈),一个块上入队n个任务的开销几乎和入队1个任务的开销相同,出队同理。这是真正的性能提升的原因。

生产者队列列表

该设计需要维护所有生产者队列(LIFO)列表,这个列表是使用尾指针和每个生产者的入队next指针来实现的。尾指针最初指向空;当一个新的生产者被创建时,它首先读取尾部,然后使用尾部的设置,然后使用CAS操作将尾部(如果它没有改变)设置到新的生产者。生产者不会从列表中删除,仅标记为不活动。当一个消费者想要出列时,它只需寻找一个带有元素的SPMC队列的生产者列表。

出队策略

消费者可以将令牌传递给出队操作。这个令牌的目的是加速选择一个合适的内部生产者队列,从中尝试出列队列。每个消费者都被分配一个自动递增的偏移量,代表它应该从中执行出队操作的生产者队列的索引。以这种方式,消费者尽可能公平地分配生产者队列。然而,并不是所有的生产者都有相同数量的可用元素,并且一些消费者可能消耗得比其他消费者快。为了解决这个问题,第一个消费者从同一个内部生产者队列中消耗了窗口大小个项目,所有消费者将在下一个出队操作时开始从下一个生产者队列出队。同时,如果消费者的指定队列中没有可用的元素,它将转到具有可用元素的下一个队列。这种简单的启发式算法非常高效,能够将消费者与生产者进行之间的资源竞争尽可能减少,从而带来出队性能提升。

注:详细设计可查看:http://moodycamel.com/blog/2014/detailed-design-of-a-lock-free-queue

一种高性能无锁队列设计相关推荐

  1. 你应该知道的高性能无锁队列Disruptor

    1.何为队列 听到队列相信大家对其并不陌生,在我们现实生活中队列随处可见,去超市结账,你会看见大家都会一排排的站得好好的,等待结账,为什么要站得一排排的,你想象一下大家都没有素质,一窝蜂的上去结账,不 ...

  2. 无锁队列设计思路以及简要代码

    文章目录 非并发的一写一读环形队列 多读多写环形队列 非并发的一写一读环形队列 读指针: 1.先判断是否有数据 2.读取数据 3.操作指针 写指针: 1.先判断空间是否足够 2.写入数据 3.操作指针 ...

  3. 深入理解高并发技术dpdk无锁队列

    前两周给大家直播分享,并发技术全景(从硬件,操作系统,虚拟机/标准库,编程语言等) 上半场(5个小时):并发/并行技术全景指南 下半场(5个小时):人生的下半场,你准备好了吗 最后我上周还布置了一个作 ...

  4. 无锁队列的几种实现及其性能对比

    一.无锁队列用在什么样的场景? 当需要处理的数据非常多,比如行情数据,一秒处理非常多的数据的时候,可以考虑用无锁队列.但是如果一秒只需要处理几百或者几千的数据,是没有必要考虑用无锁队列的.用互斥锁就能 ...

  5. linux无锁队列性能对比,无锁队列的一种实现

    队列作为最常用的基础数据结构之一,相信大家都已经非常非常熟悉了,这里省略关于队列的介绍.在平时开发中队列的出现频率非常非常高,因此我们也会很关心队列的性能问题.当并发访问队列时,队列的性能往往受到同步 ...

  6. 无锁队列Disruptor

    1.何为队列 听到队列相信大家对其并不陌生,在我们现实生活中队列随处可见,去超市结账,你会看见大家都会一排排的站得好好的,等待结账,为什么要站得一排排的,你想象一下大家都没有素质,一窝蜂的上去结账,不 ...

  7. 基于数组的无锁队列(译)

    2019独角兽企业重金招聘Python工程师标准>>> 1 引言 最近对于注重性能的应用程序,我们有了一种能显著提高程序性能的选择:多线程.线程的概念实际上已经存在了很长时间.在过去 ...

  8. linux 无锁队列覆盖问题,无锁队列杂谈

    质量最大vczh粉(402740419) 10:13:17 nobody(1575393351)  10:10:09 无锁队列,怎么可能 ? 质量最大vczh粉(402740419) 10:13:23 ...

  9. mysql8.0源代码解析_源码解读:MySQL 8.0 InnoDB无锁化设计的日志系统

    原标题:源码解读:MySQL 8.0 InnoDB无锁化设计的日志系统 作者介绍 张永翔,现任网易云RDS开发,持续关注MySQL及数据库运维领域,擅长MySQL运维,知乎ID:雁南归. MySQL ...

最新文章

  1. FilteredTextBoxExtender
  2. Chrome浏览器扩展开发系列之五:Page Action类型的Chrome浏览器扩展
  3. C# - 值类型、引用类型走出误区,容易错误的说法
  4. 2022. 将一维数组转变成二维数组
  5. “约见”面试官系列之常见面试题第四十一篇之VUE生命周期(建议收藏)
  6. HTML+CSS+JS实现 ❤️简单的翻纸牌记忆游戏❤️
  7. [NOIP2018]铺设道路
  8. vtkSuperquadricSource:创建以原点为中心的多边形超二次曲面
  9. 20190703 日子
  10. 《Effective Java 3rd》读书笔记——创建和销毁对象
  11. 通过EasyRecovery如何恢复被永久删除的音频?
  12. Redis集合 安装 哨兵集群 安全配置 redis持久化
  13. 网易云参数解析(多图)
  14. 帝国CMS采集帝国模板程序通用
  15. win10下装mysql-5.7.18-winx64
  16. 学习系列之天眼查爬虫
  17. phpcms v9 二次开发 前台上传图片
  18. Educational Codeforces Round 123 (Rated for Div. 2)(ABCDE)
  19. c语言求字符串转换成双精度_C语言如何输出双精度浮点型数据
  20. 动态系统建模与分析_伯德图

热门文章

  1. Unity生成随机数
  2. MATLAB随机森林计算重要性
  3. 计算机系统论文摘要,计算机系统结构论文摘要怎么写 计算机系统结构论文摘要范文参考...
  4. 助力 AI 银行发展 网易智企打造一站式金融服务
  5. [Windows]删除我的电脑WPS网盘等盘符
  6. 闲鱼无法确认收货显示服务器繁忙,闲鱼不确认收货怎么办?解决办法都是这样的...
  7. 一个简单的swap交换函数
  8. 文档在线化管理系统Confluce使用
  9. php使用PdfParser搭配tcpdf解析pdf文件
  10. java代码质量 圈复杂度,代码圈复杂度(Cyclomatic Complexity,CC)和Oclint工具 介绍...