1.数据结构:
JDK1.7底层采用分段数组+链表实现
JDK1.8底层采用数组+链表或者红黑树实现
2.锁机制:
JDK1.7 的 ConcurrentHashMap 是由一个 Segment 数组组成的,Segment 类似于小 HashMap,每个 Segment 内部有一个 HashEntry[]。Segment 数组初始化后大小固定,而 HashEntry[] 可以扩容。每个 Segment 内部有一把 ReentrantLock,实现分段加锁。当多个线程同时修改同一个 Segment 的数据时,会竞争这把锁,从而保证线程安全。
JDK1.8的ConcurrentHashMap和HashMap的数据结构完全一样,主要通过 volatile + CAS 或者 synchronized 来实现的线程安全的。
在 JDK1.8 中,ConcurrentHashMap 的并发写流程首先尝试通过 CAS 操作将节点放入空桶,实现无锁插入;如果失败,就使用 synchronized 锁住当前桶的头节点进行写操作,而不是锁整个 Segment,这大大减小了锁粒度。读操作则完全无锁,依赖 volatile 保证可见性。链表太长还会转红黑树优化查询性能,整体上比 JDK1.7 的分段锁机制更细粒度、更高性能