ConcurrentLinkedQueue源码解析
ConcurrentLinkedQueue源码解析
ConcurrentLinkedQueue是一个以链表实现的线程安全的队列
初始化
Queue<String> queue = new ConcurrentLinkedQueue();
初始化具体实现
private transient volatile Node<E> head;// 头部节点()
private transient volatile Node<E> tail;// 尾部节点()
public ConcurrentLinkedQueue() {
//生成一个节点,并用head和tail都指向它,因为此时的Queue中并没有添加任何东西,head和tail指向同一个节点
head = tail = new Node<E>(null);
}
ConcurrentLinkedQueue是由node类实现的,大略看看这个类的构造
private static class Node<E> {
volatile E item;
volatile Node<E> next;//这里可以说明ConcurrentLinkedQueue是以链表实现的
Node(E item) {
UNSAFE.putObject(this, itemOffset, item);
}
...
}
添加元素
// 循环向队列中添加字母表中字母
for (int i = 0; i < 24; i++) {
queue.add( String.valueOf((char) (97 + i)) );
}
add 方法
public boolean add(E e) {
return offer(e);
}
offer 方法
🔔 在阅读offer源码前,希望你能带上C++的指针思想
public boolean offer(E e) {
// 判断e是否是一个空指针,或空对象,如果是空,直接抛出异常
checkNotNull(e);
// 生成新节点
final Node<E> newNode = new Node<E>(e);
// 循环,t指向tail(尾部节点),p指向t,也就是p指向tail,这是一个自旋,因为多个线程操作链表时,举例A、B线程,他们
// 还没有开始添加元素时p指向最后一个节点i,如果A线程已经添加了一个新节点k,此时的p应该指向k,而B线程的p还指向原节点i,
// 这显然不行!for循环内用了CAS原理保证了同一时刻只有一个线程能操作成功,但是不可能A线程添加成功了,B线程添加就失败吧,
// 这也不行,所以用自旋,如果CAS失败,就更新p的指向,直至B线程成功添加为止
for (Node<E> t = tail, p = t;;) {
// 用q记录p的下一个节点
Node<E> q = p.next;
// 判断p.next是否是null,是null证明p已经指向链表的最后一个节点
if (q == null) {
// if(q==null)成立,说明p是最后一个节点了
// 调用casNext方法比较p.next指向是否为null(CAS原理),如果是则更新p.next的值,把p.next指向newNode
// CAS作用:多线程操作下,可能A线程进行到此处,而B线程已经完成了对链表的add操作,等到A继续运行时,p一定不是
// 最后一个节点,利用cas乐观锁的机制,验证p.next是否还是null,如果是null证明其他线程并没有对p操作过,此时
// 可以完成将p.next指向newNode,如果不是null,那么if判断为false,跳出if
if (p.casNext(null, newNode)) {
// 此时CAS成功了,p的next属性已经指向newNode了,注意:p.casNext(null, newNode)仅修改了p的next的指向,
// 并没有修改p的指向,也就是说p和t指向的还是原来的tail;
//一次跳两个节点更新tail指向
if (p != t) // hop two nodes at a time
casTail(t, newNode); // Failure is OK.
return true;
}
}
else if (p == q)
p = (t != (t = tail)) ? t : head;
else
p = (p != t && t != (t = tail)) ? t : q;
}
}
ConcurrentLinkedQueue 每隔一次,调整一次tail的指向,有助于减少在高度并发环境下的循环次数,提高效率,这块理解起来有难度!
本文来自博客园,作者:勤匠,转载请注明原文链接:https://www.cnblogs.com/JarryShu/articles/18198869
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现