sizeCtl 是 ConcurrentHashMap 的核心控制变量,兼具初始化、扩容控制与并发协调三重职责;其负数值表示扩容中(-1为初始化,-N表N-1线程参与),0表示未初始化,正数为无并发时的扩容阈值。

ConcurrentHashMap 的 sizeCtl 是一个核心控制变量,它同时承担初始化、扩容控制和并发协调三重职责,不是单纯的“大小阈值”。
sizeCtl 的多重语义
sizeCtl 是一个 volatile int 字段,其取值不同代表不同状态:
- 负数:表示有线程正在扩容(如 -1 表示初始化中,-N 表示有 N-1 个线程参与扩容)
- 0:表示未初始化,table 为空,下次 put 会触发初始化
- 正数:初始化完成后的扩容阈值(即 table.length * 0.75),但仅在无并发扩容时有效
初始化时 sizeCtl 的作用
首次 put 时若 table 为 null,会调用 initTable() 尝试初始化:
- 先用 CAS 将 sizeCtl 设为 -1,成功者获得初始化权
- 失败者自旋等待,直到 table 不为 null 或 sizeCtl > 0
- 初始化完成后,sizeCtl 被设为 threshold(即 16 * 0.75 = 12)
扩容时 sizeCtl 的协同机制
当元素数量超过 sizeCtl(且 table 不为空),触发扩容:
立即学习“Java免费学习笔记(深入)”;
- 线程尝试用 CAS 将 sizeCtl 从旧阈值更新为负数(如从 12 → -1),成功者启动扩容
- 其他线程发现 sizeCtl
- 扩容结束前,sizeCtl 值形如 -(1 + 扩线程数),例如 -3 表示已有 2 个线程在扩容
- 全部迁移完成后,sizeCtl 被设为新表的扩容阈值(如新容量 32 → sizeCtl = 24)
注意:sizeCtl 不是实时 size
它不反映当前实际元素个数(那是 baseCount + CounterCell 数组之和),也不直接等于 capacity。它的核心角色是“状态信号量+阈值缓存”,所有结构变更都需先与 sizeCtl 协调,避免竞争破坏一致性。


















