面试刷题必备!ConcurrentLinkedQueue源码与优化解析

软件求生 2025-04-03 11:13:38



上个月,我的朋友阿星去面试了一家知名互联网大厂,回来就和我吐槽:“这年头社招面试太卷了!我一面直接问我ConcurrentLinkedQueue的源码,看得我头皮发麻……”

听到这里,我拍了拍阿星的肩膀,笑道:“别慌,这东西看似复杂,其实只要抓住核心逻辑,完全可以手撕源码!”于是,我给他讲了一遍ConcurrentLinkedQueue的实现原理,结果他二面的时候,侃侃而谈,直接拿下了Offer!

今天,我就把这次分享的内容整理出来,给各位Java工程师们分享一波“并发队列ConcurrentLinkedQueue的核心原理与源码解析”。这篇文章适用于有一定Java并发基础的同学,建议大家先了解CAS和Unsafe的基本概念,再来看这篇文章,会更有收获!

并发队列ConcurrentLinkedQueue简介

在Java的并发编程里,我们经常会遇到高并发环境下的队列需求,比如高性能的任务调度、生产者消费者模型等。在这种情况下,普通的LinkedList显然无法满足需求,因为它的操作不是线程安全的。如果加synchronized锁,性能又会大打折扣。因此,JDK提供了一种无锁(lock-free)、基于CAS(Compare-And-Swap)实现的高效并发队列——ConcurrentLinkedQueue。

ConcurrentLinkedQueue的特点

无锁:使用CAS(乐观锁)机制来保证并发安全,不会因为锁竞争导致线程阻塞。

非阻塞:它不会因为某个线程执行慢而阻塞其他线程,保证高吞吐量。

高效:适用于高并发场景,避免了synchronized带来的性能问题。

FIFO(先进先出):它是一个基于链表的队列,符合FIFO的特性,保证元素的入队和出队顺序。

ConcurrentLinkedQueue的数据结构

我们先来看ConcurrentLinkedQueue的数据结构,它的核心是一个单向链表,主要包含两个重要的指针:

head(头指针):指向队列的第一个有效节点

tail(尾指针):指向队列的最后一个节点

这里使用了volatile关键字,保证可见性,使得多个线程可以正确地访问这些变量的最新值。

Node内部结构

队列中的每个元素被封装成一个Node节点,Node是一个静态内部类,结构如下:

注意:

item存储实际数据,可以为空(表示该节点已删除,但还未被垃圾回收)。

next指向下一个节点,用于连接链表结构。

入队(offer方法)源码解析

当我们调用offer(E e)方法时,队列会将新元素追加到队尾。由于是无锁队列,这里主要依赖CAS来保证线程安全。让我们看看源码:

offer方法的执行逻辑

创建新节点:new Node<>(e)

遍历找到队尾:

p表示当前遍历的节点,初始值是tail(尾指针)。

q = p.next,如果q==null,说明p是当前的最后一个节点。

CAS插入新节点:

p.casNext(null, newNode):如果p.next还是null,就把新节点挂上去,入队成功。

casTail(t, newNode):成功后,CAS更新tail指向新节点。

如果失败(队尾已经改变),则重新尝试入队。

出队(poll方法)源码解析

当我们调用poll()方法时,队列会返回并删除头部的元素。我们来看下源码:

poll方法的执行逻辑

从head开始遍历

尝试CAS清空item,如果成功,则返回item,并尝试更新head指针。

如果当前节点为空或已经被删除,继续向下遍历。

关键技术点

1. CAS(Compare-And-Swap)

ConcurrentLinkedQueue是基于无锁(Lock-Free)机制实现的,核心就是CAS(比较并交换)。它的底层依赖Unsafe类,直接操作内存。

例如,队列的casNext方法是这样实现的:

2. 为什么用CAS而不是锁?

CAS是乐观锁,不会阻塞线程,性能更高。

synchronized会导致线程竞争,而CAS可以利用CPU指令级别的原子操作,避免锁开销。

适用场景

高并发队列:如任务调度、生产者-消费者模型。

消息队列:可以用作简易的消息队列。

Web请求处理:如WebSocket的消息缓冲队列。

总结

今天,我们深入剖析了ConcurrentLinkedQueue,包括:

基本结构(基于链表的无锁队列)

核心方法(offer、poll)

底层原理(CAS + Unsafe)

适用场景(高并发环境)

如果你在社招面试中遇到类似问题,现在是不是可以自信应对了呢?

END

如果你觉得这篇文章有帮助,欢迎分享给你的朋友,让更多人学会这个重要的面试知识点!

我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!

0 阅读:1
软件求生

软件求生

从事软件开发,分享“技术”、“运营”、“产品”等。