并发(7)——ConcurrentLinkedQueue源码解析

并发包之队列

在这里插入图片描述

现在我们开始讨论一下并发容器中的队列的实现,队列在并发中经常会被使用,比如AQS中的同步队列、阻塞队列等。现在我们就好好研究一下队列是如何保证线程安全的,同时我们所知道的常用的消费者生产者模式也是通过队列来实现的。

同时我们知道Kafka就是一种消息队列。

常用的并发队列有阻塞队列和非阻塞队列,阻塞队列使用锁来实现,非阻塞队列使用CAS非阻塞算法实现。我们今天来分析一下ConcurrentLinkedQueue是如何通过CAS来实现的非阻塞队列。

在这里插入图片描述

ConcurrentLinkedQueue类的关注点

HOPS的设计

该类中的 tail 和 head 是延迟更新的,两者更新触发时机为:

tail 更新触发时机:当 tail 指向的节点的下一个节点不为 null 的时候,会执行定位队列真正的队尾结点的操作,找到队尾结点后完成插入之后才会通过 casTail 进行 tail 更新;当 tail 指向的节点的下一个结点为 null 的时候, 只插入结点不更新 tail

从上面的分析中可以看出,head 和 tail 的更新是“跳着的”,即中间总是间隔了一个。那么这样设计的意图是什么呢?

如果让 tail 永远作为队列的队尾结点,实现的代码量会更少,而且逻辑更易懂。但是,这样做有一个缺点,如果大量的入队操作,每次都要执行CAS进行 tail 的更新,汇总起来对性能也会是大大的损耗。如果能减少 CAS 更新的操作,无疑可以大大提升入队的操作效率。

注意点

ConcurrentLinkedQueue 使用 CAS 非阻塞算法实现,使用CAS解决了当前节点与next节点之间的安全链接和对当前节点值的赋值。由于使用CAS没有使用锁,所以获取size的时候有可能进行 【offer】 、【pool】或者【remove】等才做,导致获取的元素个数不精确,所以在并发情况下size函数不是很有用。

参考并感谢

[1] https://juejin.im/post/5aeeae756fb9a07ab11112af

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值