基于单链表的无界无锁并发队列及入队、出队方法技术

技术编号:38320473 阅读:12 留言:0更新日期:2023-07-29 09:02
本发明专利技术公开基于单链表的无界无锁并发队列及入队、出队方法,涉及数据结构技术领域,拟解决现有基于单链表的队列无法保证尾指针更新的单向性,且需对节点内容的数据进行拷贝影响队列执行性能的问题;本发明专利技术在基于单链表的无锁队列中设有dumb节点,在队列仅剩最后一个元素且需要对该元素进行出队时,入队一个dumb节点,并将原有节点出队,在队列为空时dumb节点将作为哨兵节点存在;本发明专利技术能够解决现有单链表无锁队列实现中提到的问题,既保证了尾指针更新的单向性,又无需进行对节点内容的数据拷贝,提升了队列的执行性能。提升了队列的执行性能。提升了队列的执行性能。

【技术实现步骤摘要】
基于单链表的无界无锁并发队列及入队、出队方法


[0001]本专利技术涉及数据结构
,具体涉及基于单链表的无界无锁并发队列及入队、出队方法。

技术介绍

[0002]基于链表的无锁队列有多种实现方式,其中一种比较常见的是基于单向链表的无锁队列。基于单向链表的无锁队列的主要思想是使用两个指针,一个指向队列的头结点,一个指向队列的尾结点。入队操作是将新结点链接到尾结点的后面,并更新尾指针。出队操作是将头结点的后继结点出队,并更新头指针。为保证头尾指针不为NULL,避免一些并发问题,即使是一个空的队列,其中也至少会保留一个哨兵节点,其中不保存数据。
[0003]一个基本的基于链表的无锁队列的实现步骤如下:
[0004]1.入队操作:
[0005]·
创建一个新结点,设置其值和next指针为NULL。
[0006]·
使用CAS操作将尾结点的next指针指向新结点,如果成功,则说明没有其他线程竞争,否则重试。
[0007]·
使用CAS操作将尾指针指向新结点,如果失败,则说明其他线程已经更新了尾指针,
[0008]不影响结果。
[0009]2.出队操作:
[0010]·
获取头结点和头结点的后继结点,如果后继结点为NULL,则说明队列为空,返回NULL。
[0011]·
使用CAS操作将头指针指向后继结点,如果成功,则说明没有其他线程竞争,否则重试。
[0012]·
返回后继结点的值,并释放头结点
[0013]然而,在代码实现中,保留一个常空的头节点不是一个很好的做法。在队列非空时,队列的尾指针每次会指向新加入的节点,这种单向更新能够简化无锁队列的实现,提升查询效率。而一旦队列从非空变为空,尾指针将被迫指向头节点,这破坏了尾指针更新的单向性,可能会使得代码实现变得更加复杂。为避免这一问题,部分已有实现选择不保留一个常空的哨兵节点,而是使用数据拷贝的方式传出最后一个节点的值,然而这种做法亦存在问题,如果队列元素本身结构较大,拷贝同样会引入过大开销,导致队列本身性能下降。

技术实现思路

[0014]为了解决上述现有技术中存在的问题,本专利技术拟提供了基于单链表的无界无锁并发队列及入队、出队方法,拟解决现有基于单链表的队列无法保证尾指针更新的单向性,且需对节点内容的数据进行拷贝影响队列执行性能的问题。
[0015]基于单链表的无界无锁并发队列,队列中设有dumb节点,在队列仅剩最后一个元
素且需要对该元素进行出队时,入队一个dumb节点,并将原有节点出队,在队列为空时dumb节点将作为哨兵节点存在。
[0016]优选的,所述队列中用于链接链表节点的指针分为两部分,前半部分为更新计数,后半部分为地址部分,指向下一个节点的地址,并且此结构将作为一个数值类型进行存储。
[0017]基于单链表的无界无锁并发队列的入队方法,包括两步CAS操作,第一步是将新节点添加至尾指针指向的节点的后继上,如果失败即重试;第二步是将尾指针更新至新插入的节点上,这一步无需重试,可由其他线程代为完成。
[0018]基于单链表的无界无锁并发队列的出队方法,若队列中有两个以上的节点,将头节点出队即可;若队列中仅剩一个节点,则检查此节点有无内容;若有,则入队一个dumb节点,并将原有节点出队;若无,返回NULL,表示此队列为空。
[0019]基于单链表的无界无锁并发队列的入队方法,包括如下步骤:
[0020]第一步:获取tail_指向的节点tail;
[0021]第二步:获取tail的后继节点next;
[0022]第三步:判断尾指针是否没有变动,即tail_是否等于tail,若不等于则返回第一步,若等于则判断next是否为空;
[0023]第四步:若next不为空说明有其他线程添加了新节点,使用一个cas操作将tail_时戳+1,指针修改为新节点;若为空则将新元素时戳修改为tail的时戳,后继指针赋null,再使用一个cas操作将tail的时戳+1,后继指针修改为新节点;
[0024]第五步:若后继指针修改为新节点修改成功则使用一个cas操作将tail_时戳+1,指针修改为新节点;若修改失败则返回第一步。
[0025]基于单链表的无界无锁并发队列的出队方法,包括如下步骤:
[0026]第一步:获得head_指向的节点head;
[0027]第二步:获得tail_指向的节点tail;
[0028]第三步:获得head的后继next;
[0029]第四步:判断头指针是否没有变动即head_是否等于head,若是进行下一步,若否返回第一步;
[0030]第五步:判断队列是否为空,即head是否等于tail,若等于则进行下一步,若否则使用一个cas操作将head_时戳+1,指针修改为next,若修改成功则返回head节点则流程结束,若修改失败则返回第一步;
[0031]第六步:检查head的后继是否为null,若是则进行下一步,若否则说明有新节点入队,更新tail_即使用一个cas操作将tail_时戳+1,指针修改为新节点,而后返回第一步;
[0032]第七步:检查head是否为dumb节点,若是则说明队列无元素可返回,返回null而后结束,若否则说明当前队列只有一个元素,创建一个dumb节点入队下一轮将此节点出队,而后返回第一步。
[0033]本专利技术的有益效果包括:
[0034]1、本专利技术能够解决现有单链表无锁队列实现中提到的问题,既保证了尾指针更新的单向性,又无需进行对节点内容的数据拷贝,一定程度上提升了队列的执行性能。
[0035]2、在实际使用场景中,本专利技术相比C++boost::lockfree::queue即目前主流的无锁队列实现,性能存在较大提升,在使用本专利技术实现的mpmc(多生产者多消费者)queue,分
别进行每核一定数量级(N)的入队和出队操作,在不同N取值下,性能最终要优于boost库队列约30%左右。
附图说明
[0036]图1为实施例1基于单链表的无界无锁并发队列的结构。
[0037]图2为实施例1基于单链表的无界无锁并发队列的链表节点指针结构。
[0038]图3为实施例1涉及基于单链表的无界无锁并发队列的入队方法。
[0039]图4为实施例1涉及基于单链表的无界无锁并发队列的出队方法。
[0040]图5为实施例1涉及现有技术与本专利技术性能对比图。
具体实施方式
[0041]为使本申请实施例的目的、技术方案和优点更加清楚,下面将结合本申请实施例中附图,对本申请实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅是本申请一部分实施例,而不是全部的实施例。因此,以下对在附图中提供的本申请的实施例的详细描述并非旨在限制要求保护的本申请的范围,而是仅仅表示本申请的选定实施例。基于本申请的实本文档来自技高网
...

【技术保护点】

【技术特征摘要】
1.基于单链表的无界无锁并发队列,其特征在于,队列中设有dumb节点,在队列仅剩最后一个元素且需要对该元素进行出队时,入队一个dumb节点,并将原有节点出队,在队列为空时dumb节点将作为哨兵节点存在。2.根据权利要求1所述的基于单链表的无界无锁并发队列,其特征在于,所述队列中用于链接链表节点的指针分为两部分,前半部分为更新计数,后半部分为地址部分,指向下一个节点的地址,并且此结构将作为一个数值类型进行存储。3.基于单链表的无界无锁并发队列的入队方法,其特征在于,包括两步CAS操作,第一步是将新节点添加至尾指针指向的节点的后继上,如果失败即重试;第二步是将尾指针更新至新插入的节点上,这一步无需重试,可由其他线程代为完成。4.基于单链表的无界无锁并发队列的出队方法,其特征在于,若队列中有两个以上的节点,将头节点出队即可;若队列中仅剩一个节点,则检查此节点有无内容;若有,则入队一个dumb节点,并将原有节点出队;若无,返回NULL,表示此队列为空。5.根据权利要求3所述的基于单链表的无界无锁并发队列的入队方法,其特征在于,包括如下步骤:第一步:获取tail_指向的节点tail;第二步:获取tail的后继节点next;第三步:判断尾指针是否没有变动,即tail_是否等于tail,若不等于则返回第一步,若等于则判断next是否为空;第四步:若next不为空说明有其他线程添加了新...

【专利技术属性】
技术研发人员:聂晓文黄麒之
申请(专利权)人:电子科技大学
类型:发明
国别省市:

网友询问留言 已有0条评论
  • 还没有人留言评论。发表了对其他浏览者有用的留言会获得科技券。

1