concurrenthashmap中红黑树节点由treebin包装管理,真正参与并发操作的是treebin;树化需同时满足链表长度≥8且数组长度≥64;treebin负责锁控制与树结构维护,不存key/value;节点数≤6时自动退化为链表。

ConcurrentHashMap 中的红黑树节点(TreeNode)不是直接存入数组的,而是被包装在 TreeBin 节点里统一管理。真正参与并发操作的是 TreeBin,它作为桶(bucket)的头节点,负责协调对整棵红黑树的读写,同时屏蔽底层树结构的复杂性。
TreeBin 是红黑树的并发门面
TreeBin 本身不存 key/value,只维护红黑树根、锁状态和等待线程队列。它的核心作用是:把对整棵树的并发访问,收敛到对一个轻量级对象的同步控制上。
- 当某个桶决定树化时,所有链表节点会被重构为
TreeNode,再由TreeBin持有其根节点 - 后续对该桶的所有
put/get/remove操作,都先获取TreeBin的synchronized锁(锁的是TreeBin实例本身) - 读操作(如
get)在持有锁期间执行查找,但不会阻塞其他读——因为红黑树结构稳定,且TreeNode字段(如left/right/parent)均为volatile或通过锁保障可见性
树化触发条件比表面更严格
不是链表一满 8 个就立刻转树。JDK 8 要求两个条件**同时满足**:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 链表长度 ≥ 8(
TREEIFY_THRESHOLD = 8) - 哈希表数组长度 ≥ 64(
MIN_TREEIFY_CAPACITY = 64)
如果数组太小(比如刚初始化或还在扩容中),即使链表很长,也优先选择扩容而非树化——避免小表上过早引入树结构带来的额外开销和锁竞争。
写操作锁粒度精准落在 TreeBin 上
与 HashMap 不同,ConcurrentHashMap 对树的操作不会锁整个 map,也不会锁整个 table 数组:
- 仅当线程定位到某个已树化的桶(即头节点是
TreeBin)时,才对这个TreeBin对象加synchronized - 多个线程操作不同桶的树,互不影响;同一桶的写操作则串行执行,保证树结构一致性
- 插入/删除可能触发树再平衡,这些修改都在锁内完成,且关键字段(如
root、节点颜色、子引用)更新均受锁保护
退化机制保障低冲突场景效率
红黑树不是“一树永逸”。当树中节点数 ≤ 6(UNTREEIFY_THRESHOLD = 6)时,会自动退化回链表:
- 退化发生在下一次写操作中(如
remove后节点减少),由当前持有TreeBin锁的线程完成 - 退化后,桶头节点从
TreeBin变回普通Node,后续操作切换为链表逻辑,降低内存与计算开销 - 该机制让 ConcurrentHashMap 能动态适应哈希分布变化,避免在低冲突场景下为树结构付出不必要成本
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










