Exchanger是Java并发包中专为两个线程双向同步交换数据设计的会合点同步原语,必须成对抵达才能原子交换数据,仅支持严格配对、无缓冲、零拷贝引用传递,底层基于CAS+park/unpark实现,不适用于多于两个线程的场景。

Exchanger 是 Java 并发包中专为两个线程之间双向、同步交换数据设计的轻量级同步原语,不是通用队列或广播工具,也不支持多于两个线程的协作。它的本质是一个“会合点(Rendezvous Point)”,强调严格配对、原子交换、无缓冲、零拷贝引用传递。
核心行为:必须成对抵达才能交换
调用 exchanger.exchange(data) 的线程会立即挂起(WAITING 状态),不忙等、不自旋,而是让出 CPU。只有当另一个线程也调用同一 Exchanger 实例的 exchange() 方法时,两者才被唤醒并完成一次原子交换——你拿到我的数据,我拿到你的数据,同时继续执行。
- 若仅一个线程调用,它将无限等待(除非设超时)
- 三个线程共用同一个 Exchanger:前两个配对成功,第三个一直阻塞,无法参与本次交换
- 不存在“先来先服务”或排队机制,只认“两人齐到”
底层同步机制:CAS + park/unpark + 内存屏障
Exchanger 不依赖 synchronized 或 ReentrantLock,而是基于 JVM 底层能力实现高效协作:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 用 volatile 字段标记等待状态,用 CAS 原子更新内部槽位(slot)
- 线程挂起靠
LockSupport.park(),唤醒靠unpark(),无锁且低开销 - 交换前后插入内存屏障,天然保证 happens-before 关系:A 交换前的写对 B 交换后的读可见,反之亦然
- 高并发下自动启用 arena 扩展机制,分散 CAS 冲突,但每次交换仍严格限定在单个槽位、两个线程
超时控制:避免永久阻塞
使用 exchange(data, timeout, unit) 可设定等待上限:
立即学习“Java免费学习笔记(深入)”;
- 超时由操作系统定时器 + JVM 中断机制触发,非轮询判断
- 超时后线程抛出
TimeoutException,并自动清理槽位状态 - 已超时退出的线程不会参与后续配对,不影响新线程使用该 Exchanger
典型适用场景
Exchanger 天然适配需要严格双向协作、节奏对齐的模式:
- 双缓冲处理:线程 A 填充缓冲区1,线程 B 消费缓冲区2;交换后 A 改用缓冲区2,B 改用缓冲区1
- 流水线阶段配对:如生产者-校验者、采集-预处理,双方各持一份中间结果,交换即推进下一阶段
- 测试与模拟协作:验证两个线程能否在精确时机完成数据交接

















