笔记簿
ᴄᴏᴅɪɴɢ ɪs ᴀʀᴛ
首页
关于
搜索
登录
注册
ConcurrentHashMap - 如何实现线程安全
ConcurrentHashMap 通过细粒度锁和 CAS 操作实现高效线程安全,具体实现因 Java 版本而异: ### **Java 7 实现(分段锁)** 1. **数据结构** - 由多个 `Segment` 组成,每个 `Segment` 是一个独立的哈希表(数组 + 链表)。 - 默认 16 个 Segment,并发度由 `concurrencyLevel` 决定。 2. **线程安全** - **分段锁机制**:操作数据时,仅锁定对应 `Segment`,不同 Segment 可并行操作。 - **锁粒度**:Segment 级别,减少锁竞争,提升并发性能。 3. **加锁方式** - `put` 操作时,通过哈希确定 Segment,使用 `ReentrantLock` 锁定该 Segment。 - 其他线程访问不同 Segment 无需阻塞。 --- ### **Java 8 实现(CAS + synchronized)** 1. **数据结构** - `Node 数组 + 链表 + 红黑树`,类似 HashMap,但线程安全设计不同。 - 链表长度 ≥8 时转为红黑树,哈希冲突时查询效率更高。 2. **线程安全** - **CAS 无锁化**:空桶插入使用 CAS 设置头节点,避免加锁。 - **细粒度锁**:非空桶时,仅 `synchronized` 锁定头节点,锁粒度细化到单个桶。 3. **加锁方式** - **插入流程**: 1. 计算哈希定位到桶。 2. 若桶为空,CAS 写入头节点。 3. 若桶非空,`synchronized` 锁住头节点,遍历链表/树插入或更新。 - 不同桶的操作完全并行,仅相同桶的线程竞争锁。 4. **扩容优化** - 多线程协作扩容:当检测到扩容,线程协助迁移数据,提升效率。 --- ### **线程安全共性** - **弱一致性迭代器**:迭代过程中数据可能被修改,不会抛出 `ConcurrentModificationException`。 - **原子性保证**:复合操作(如 `putIfAbsent`)通过锁或 CAS 保证原子性。 - **高效统计**(Java 8):`size` 使用 `LongAdder` 思想,通过多个计数器减少竞争。 --- ### **总结** - **Java 7**:分段锁降低锁竞争,提升并发度。 - **Java 8**:CAS + `synchronized` 细化锁粒度,结合红黑树优化查询,并发性能更优。 通过上述机制,ConcurrentHashMap 在保证线程安全的同时,显著减少了锁竞争,适用于高并发场景。