Exchanger 底层通过 CAS 实现无锁配对,核心是“撞上就换”:两线程在 slot 或 arena 槽位竞争 CAS,成功者挂起,失败者唤醒对方并完成数据交换;超时与中断仅控制线程状态,CAS 负责原子性清理。

Exchanger 底层靠 CAS 实现无锁配对,核心不是“排队等”,而是“撞上就换”——两个线程在同一个内存位置(slot)用 CAS 争一次,成功者留下数据并挂起,失败者立刻尝试配对或换槽位。
Slot 槽位是 CAS 的操作靶点
每个 Exchanger 实例维护一个 volatile 的 slot 字段(本质是 AtomicReference
- 若 CAS 成功 → 表示自己是“先到者”,把数据存进 slot,随即 park 挂起,等待唤醒
- 若 CAS 失败 → 说明 slot 已被另一个线程抢先占了,此时直接读取 slot 中对方的 Node,把自己的数据写入其 match 字段,并用 unpark 唤醒对方
CAS 配合 volatile 保证可见性与原子性
slot 是 volatile 的,确保所有线程看到的是最新值;而 CAS 操作本身由 Unsafe.compareAndSwapObject 提供硬件级原子性。整个交换过程不依赖 synchronized 或 Lock,仅靠一次 CAS 写入 + 一次 CAS 清空(将 slot 置为 null)完成配对闭环:
- 第一个线程写入 slot 后,第二个线程能立即通过 volatile 读看到该 Node
- 第二个线程用 CAS 把 slot 从 Node 状态改回 null,同时把双方数据绑定到各自 Node 的 item/match 字段中
- 这一读-改-写序列构成一次原子交换,不存在中间态被第三方干扰的可能
高并发下升级为 arena 多槽位,仍靠 CAS 逐槽竞争
当多个线程频繁争抢同一 slot 导致 CAS 失败率升高时,Exchanger 自动启用 arena(数组)机制,每个线程根据自身 hash 或轮询选择不同索引的 slot 进行 CAS:
立即学习“Java免费学习笔记(深入)”;
- arena 是 Node[] 数组,每个元素是一个独立的 slot
- 线程不再只盯 slot 字段,而是按规则尝试 arena[i],仍用 CAS 更新对应位置
- 每个成功的交换仍严格限定在单个 arena 元素内,仍是“两线程一槽位一 CAS 配对”
超时与中断不影响 CAS 逻辑,只控制线程状态
CAS 本身不处理超时,但超时机制通过操作系统定时器 + Thread.interrupt() 协同工作:
- 线程 park 时可设超时时间,到期自动唤醒并抛 TimeoutException
- 唤醒后检查是否已配对:若未配对,CAS 将对应 slot 清空,避免残留阻塞后续线程
- 中断发生时,park 返回,线程抛 InterruptedException,同时 CAS 清理现场,保障 slot 可重用


















