reservationnode 是 concurrenthashmap 扩容时标记桶正迁移的占位节点,hash=-3、字段全 null,不存数据;putval 中遇 reserved 会调用 helptransfer 协助扩容。

ReservationNode 是 ConcurrentHashMap 内部用于“占位”的特殊节点,不存储实际键值对,只在扩容(transfer)过程中临时标记某个桶(bin)正在被迁移,防止其他线程重复处理或写入冲突。
ReservationNode 的作用场景
它只在 transfer 方法执行扩容时出现,当一个线程开始迁移某个桶的链表或红黑树时,会先用 ReservationNode 占住该桶头结点位置。这样其他线程再尝试对该桶做 put、compute 等操作时,能立即感知到“此桶正在迁移”,从而主动协助扩容或退避重试。
它不是用户可创建或接触的节点类型,纯属内部协调机制,JDK 代码中甚至没有公开构造器,仅通过静态工厂方法 new ReservationNode() 在 transfer 中按需生成。
ReservationNode 的关键特征
- hash 值固定为
RESERVED(即 -3),区别于普通节点(>0)、树节点(-2)、空节点(0)、转发节点(-1) - key/value/next 字段全为
null,无业务数据,也不参与查找或遍历 - 不继承
Node,而是独立的静态内部类,仅用于标识状态 - 它的存在让
putVal中的if (fh == MOVED)判断能覆盖两种情况:已迁完(ForwardingNode)和正迁移中(ReservationNode)
它如何影响你的代码行为
你完全不需要、也不能直接使用 ReservationNode。但理解它有助于解释一些现象:
- 并发 put 时偶尔短暂变慢?可能是某线程撞上
ReservationNode,转而协助扩容(helpTransfer),这是正常协作行为 - 调试时看到某个 bin 的头节点是
ReservationNode?说明扩容正在进行,且该桶尚未处理完 - 不会出现在
entrySet()、keySet()或遍历结果中——它不参与数据视图
源码中典型判断逻辑(JDK 11+)
在 putVal 开头,会检查桶首节点:
Node<k> f; int fh;
if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
// 桶为空,尝试 CAS 插入
} else if ((fh = f.hash) == MOVED) {
// MOVED 是 ForwardingNode 的 hash(-1),表示已迁完
tab = helpTransfer(tab, f);
} else if (fh == RESERVED) {
// RESERVED 是 ReservationNode 的 hash(-3),表示正迁移中
// 此时也调用 helpTransfer 协助
tab = helpTransfer(tab, f);
}</k>可见,对 RESERVED 和 MOVED 的处理逻辑一致:触发协助扩容,保证高并发下的安全与进度推进。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











