forwardingnode是concurrenthashmap扩容时的状态标识节点,不存业务数据(key/value为null),核心作用是标记桶已迁移并携带nexttable引用;读操作自动跳转新表查找,零同步开销;写操作触发helptransfer()协助迁移;多线程协作依赖sizectl、nexttable和transferindex三字段协调。

ForwardingNode 是扩容过程中的状态标识节点
ForwardingNode 本身不存储业务数据,key 和 val 字段均为 null。它的核心作用是标记某个桶(table[i])已完成迁移,同时携带指向新表(nextTable)的引用。只要看到 ForwardingNode,就说明该位置已由某线程完成搬运,后续访问应转向新表查找或协助迁移。
读操作自动跳转,零同步开销
当 get() 或 containsKey() 等读方法命中 ForwardingNode 时,会调用其内部 find() 方法:
- 从 nextTable 字段取出新数组(该字段在 ForwardingNode 构造时强制非空,不会为 null)
- 用原哈希值 h 重新计算在新表中的索引:(nextTab.length - 1) & h
- 遍历新表对应桶的链表或红黑树;若再次遇到 ForwardingNode,继续递归跳转
整个过程无锁、无 CAS、不修改任何共享状态,多个线程并发执行互不影响。
写操作触发协助迁移
put、remove 等写操作遇到 ForwardingNode 时,行为与读不同:
使用一条命令部署ProbeChain Rydberg测试网代理节点。自动注册为Agent(NodeType=1),免gas,支持macOS/Linux/Windows。触发词:/r
- 先尝试调用 helpTransfer() 协助完成剩余迁移任务
- helpTransfer() 会检查 transferIndex,争抢未分配的迁移段(如 [i, bound) 区间)
- 抢到任务后,用 synchronized 锁住旧桶头节点,安全搬运其中所有节点到新表两个位置(i 和 i + oldCap)
这种“遇转发即协作者”的设计,把扩容压力分散到日常写请求中,避免集中阻塞。
多线程协作依赖 sizeCtl 与 transferIndex
扩容全程由三个 volatile 字段协同控制:
- sizeCtl:负值表示扩容中,如 -2 表示 1 个线程正在扩容;其高 16 位是扩容邮戳(resizeStamp),低 16 位记录参与线程数
- nextTable:扩容期间唯一的新数组引用,仅在全部迁移完成后才被置 null 并让 table 指向它
- transferIndex:原子递减,用于划分迁移任务段,确保各线程处理不同桶区间,避免重复搬运
所有迁移逻辑都基于 Unsafe 对 Node[] 元素的 volatile 读写,保障跨 CPU 核心的可见性与有序性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










