2. 并发控制的“三板斧”:CAS + synchronized + volatile
(1) CAS(Compare And Swap)——无锁的“轻功”
- 应用场景:初始化数组、插入头节点、计数(如
sizeCtl
字段)等非阻塞操作。 - 代码示例:
// 典型的CAS操作(伪代码) if (当前值 == 预期值) { 更新为新值; return true; } else { return false; }
- 优势:避免线程阻塞,适合低竞争场景。
- 缺点:高竞争时可能导致大量重试(CPU空转)。
(2) synchronized锁——精准打击的“点穴术”
- 锁对象:每个数组桶的头节点(即链表或树的根节点)。
- 锁粒度:只锁当前操作的桶,其他桶可自由访问,彻底告别“全员排队”。
- 优化:JDK1.6后
synchronized
升级为“偏向锁→轻量级锁→重量级锁”,性能媲美CAS。
举个栗子🌰:
想象一个餐厅,Hashtable
是所有人排队等一个收银台,而ConcurrentHashMap
是每个餐桌(桶)有自己的服务员(锁),顾客(线程)只需在目标餐桌前排队。
(3) volatile变量——实时更新的“监控探头”
- 应用字段:
table
数组、Node.val
、Node.next
等。 - 作用:保证多线程间的可见性,读取最新值,避免脏数据。
3. 扩容机制:多线程“搭把手”的高效迁移
CHM的扩容是“渐进式”的,不会一次性卡死所有线程,核心步骤:
- 触发条件:当元素数量超过
容量 × 负载因子
时触发扩容。 - 分配任务:每个线程处理一个“步长”(stride)的桶区间,默认16个桶。
- 迁移数据:
- 旧桶标记为
ForwardingNode
(表示正在迁移)。 - 其他线程插入数据时,发现
ForwardingNode
会主动帮忙迁移。
- 旧桶标记为
- 完成扩容:所有桶迁移后,数组大小翻倍,阈值更新。
关键代码片段(简化版):
while (正在迁移) {
if (当前线程是第一个触发扩容的线程) {
初始化新数组(双倍大小);
}
分配迁移区间(从旧数组的i到i+stride);
for (每个桶 in 分配区间) {
if (桶未被迁移) {
锁住桶头节点;
迁移链表或树到新数组;
替换为ForwardingNode;
}
}
}
为什么高效?
- 并行迁移:多线程协作,分摊迁移成本。
- 无全局锁:每个线程处理不同区间,互不干扰。
4. 哈希碰撞处理:分散与平衡的艺术
- 哈希算法:
通过高位异或,让哈希值分布更均匀,减少碰撞概率。int hash = (key.hashCode() ^ (key.hashCode() >>> 16)) & 0x7fffffff;
- 再哈希策略:若发生碰撞,先尝试链表插入,过长则转红黑树。
5. 源码中的“彩蛋”设计
- sizeCtl字段:一个int值兼任多个角色:
- 负数:表示正在初始化或扩容。
- 正数:表示扩容阈值。
- TreeBin类:红黑树的“管家”,内部用
volatile int lockState
实现读写锁,平衡树结构调整与查询的并发性。
6. 性能对比实验(附伪代码)
// 测试代码:10个线程,每个写入10000次
Map<String, Integer> map = new ConcurrentHashMap<>();
ExecutorService pool = Executors.newFixedThreadPool(10);
long start = System.currentTimeMillis();
for (int i = 0; i < 10; i++) {
pool.submit(() -> {
for (int j = 0; j < 10000; j++) {
map.put(Thread.currentThread().getName() + j, j);
}
});
}
pool.shutdown();
pool.awaitTermination(1, TimeUnit.HOURS);
System.out.println("耗时:" + (System.currentTimeMillis() - start) + "ms");
// 结果:ConcurrentHashMap通常比Hashtable快5倍以上!
总结:ConcurrentHashMap的“内功精髓”
- 锁粒度:从分段锁(JDK1.7)到桶锁(JDK1.8),锁粒度越来越细。
- 数据结构:链表转红黑树,平衡查询与插入效率。
- 并发协作:CAS + synchronized + volatile,实现无锁化与精准锁的完美结合。
最后一句金句💡:
ConcurrentHashMap的设计哲学是——“能无锁就无锁,必须锁就锁最少”。这不仅是技术的胜利,更是对“高效协作”的深刻理解!