面试题答案
一键面试锁的粒度
- 分段锁机制(JDK 1.7及之前):
ConcurrentHashMap
在JDK 1.7及之前采用了分段锁(Segment)的设计。它将数据分成多个段(Segment数组),每个段都有自己独立的锁。- 例如,当有多个线程同时访问
ConcurrentHashMap
时,不同线程可以访问不同的段,只有当线程访问同一个段时才需要竞争该段的锁。这样大大降低了锁的竞争程度,提高了并发性能。
- CAS + 同步锁(JDK 1.8及之后):
- JDK 1.8中,
ConcurrentHashMap
摒弃了分段锁机制,采用了CAS(Compare - And - Swap)操作和synchronized
关键字结合的方式。 - 在插入新元素时,首先使用CAS操作尝试直接将元素插入到相应位置。如果CAS操作失败,说明有其他线程同时进行插入操作,此时才会使用
synchronized
关键字对该位置的链表头节点或红黑树节点加锁,再进行插入操作。这种方式进一步降低了锁的粒度,只有在真正发生竞争时才会加锁。
- JDK 1.8中,
数据结构
- 数组 + 链表(JDK 1.7):
ConcurrentHashMap
在JDK 1.7中,内部数据结构是由Segment数组和每个Segment中的HashEntry数组及链表组成。- Segment继承自
ReentrantLock
,每个Segment维护着一个HashEntry数组,HashEntry数组中的每个元素又是一个链表的头节点。当发生哈希冲突时,新元素会被插入到链表的头部。这种结构在保证线程安全的同时,通过分段锁机制提高了并发访问性能。
- 数组 + 链表 + 红黑树(JDK 1.8):
- JDK 1.8的
ConcurrentHashMap
数据结构与HashMap
类似,采用数组 + 链表 + 红黑树。 - 当链表长度达到一定阈值(默认为8)且数组长度达到64时,链表会转换为红黑树,以提高查找效率。在多线程环境下,无论是链表还是红黑树的操作,都通过上述的CAS和
synchronized
机制来保证线程安全和数据一致性。例如,在红黑树节点的插入、删除操作时,会对相应的树节点加锁,以确保操作的原子性和一致性。
- JDK 1.8的