ForwardingNode 是 ConcurrentHashMap 扩容时标记已迁移桶的特殊节点,hash 值恒为 -1,不存数据,仅通过 nextTable 指向新表并在 find 时引导查找。

ForwardingNode 是 ConcurrentHashMap 在扩容期间用来标记已迁移桶的特殊节点,它本身不存数据,只指向新表,作用是引导线程跳转到新 table 继续操作。
ForwardingNode 的核心作用
当 ConcurrentHashMap 触发扩容(transfer)时,旧 table 中某些桶(bin)会被逐步迁移到新 table。为避免多线程重复迁移或读写冲突,ConcurrentHashMap 把已完成迁移的桶头节点替换成 ForwardingNode。这个节点本质是一个“指针”:
- 它的
nextTable字段指向正在构建的新 table - 它的
hash值固定为-1,这是识别 ForwardingNode 的关键标志(普通 Node 的 hash ≥ 0,TreeBin 为 -2,ReservationNode 为 -3) - 调用其
find()方法时,会直接在新 table 对应位置重新查找
什么时候会遇到 ForwardingNode?
你在并发环境下执行 get、put、compute 等操作时,若恰好访问到一个正在扩容的桶,就可能碰到 ForwardingNode:
-
get(key):发现桶首节点是 ForwardingNode → 调用其find(h, key)→ 自动转向新表查找 -
put(key, value):定位到 ForwardingNode → 不加锁直接调用helpTransfer()协助扩容,或进入新表重试 - 其他操作如
replace、remove同理,都会先检查是否为 ForwardingNode 并做相应跳转
ForwardingNode 的结构和关键方法
它继承自 Node,但只重写了 find 方法:
立即学习“Java免费学习笔记(深入)”;
-
final Node<K,V>[] nextTable;—— 指向新 table,由扩容线程传入 -
find(int h, Object k):计算k在新表中的下标i = (n - 1) & h,然后在nextTable[i]处调用find(h, k)(递归或循环查找) - 不支持
putTreeVal、不参与红黑树转换,也不存储 key/value
你不需要手动创建或使用它
ForwardingNode 完全由 ConcurrentHashMap 内部管理:
- 扩容线程在完成某个桶迁移后,用
UNSAFE.putObjectVolatile将原桶头设为 new ForwardingNode(nextTab) - 普通业务代码永远不应 new ForwardingNode 或显式判断它——所有逻辑都封装在
tabAt、casTabAt、helpTransfer等辅助方法中 - 如果你在调试时看到
ForwardingNode@xxx,说明当前正处在扩容中间态,属正常现象
理解它有助于读懂 transfer 流程和并发安全设计,但日常开发中无需干预。


















