ConcurrentLinkedQueue 基于 Michael-Scott 无锁队列算法:单向链表 + head/tail 两个 CAS 引用。入队 offer:创建新节点,CAS 挂到尾节点的 next,再 CAS 推进 tail(允许懒推进,tail 最多滞后一个节点);出队 poll:CAS 推进 head。所有竞争都收敛到单个 CAS 操作,失败重试——没有锁、没有阻塞,多线程吞吐随核数扩展。无界是重要特性,也意味着生产者失控会 OOM

与 BlockingQueue 的选择:需要「队列满了生产者等、空了消费者等」的阻塞语义——ArrayBlockingQueue(数组有界、单锁)、LinkedBlockingQueue(链表可选界、读写双锁分离,吞吐更好);需要高并发但自己处理空/满逻辑——ConcurrentLinkedQueue(poll 空返回 null,配合重试或信号量);需要优先级——PriorityBlockingQueue;零交接直传——SynchronousQueue。无锁不等于无条件更快:竞争低时锁的开销很小,无锁的 CAS 自旋反而费 CPU;竞争高时无锁的可伸缩性才体现。实现细节考点:size() 要遍历链表是 O(n) 且不精确(并发下本来就难定义)、ABA 问题在此算法中由 GC 保证节点不被复用而规避(Java 里不用担心 ABA 的说法仅限此类场景)。追问方向:链表节点的内存开销 vs 数组环形队列(JCtools 的 MPMC 数组队列为何更 cache 友好)、wait-free 与 lock-free 的区别。

(约 470 字)