ConcurrentHashMap
JDK1.7
ConcurrentHashMap 是如何保证并发安全的?使用分段锁的概念:
例如这张图,共有 256 个槽位,如果整个哈希表用一把锁,势必性能低下
如果256个槽位,每个槽位都有一把锁,性能提上去了,但是锁个数过多的话,比如哈希表扩容了,这样对系统资源的消耗就太大了
ConcurrentHashMap 使用的分段锁,如上图每四个槽位分一把锁,当一把锁管辖的数组元素同时多个线程执行(如同时更新 1 ~ 4),就会发生阻塞。
同时这里用的锁是 ReentrantLock
JDK1.8
首先放弃了分段锁的概念
在 JDK 1.8 中,ConcurrentHashMap
确实放弃了之前版本中的分段锁机制。相反,它引入了一种基于 CAS(Compare and Swap)和 synchronized 机制的全局锁策略来提供线程安全性。
在 JDK 1.8 中,ConcurrentHashMap
的内部结构被修改为了一种称为「分段数组 + 链表/红黑树」的形式。它不再使用每个段(Segment)上的锁,而是将锁的粒度缩小到更细的粒度——每个链表(或红黑树)上的节点。这使得在并发修改时只有需要锁定同一链表的部分,并发性能得到显著的提升。
此外,JDK 1.8 中的 ConcurrentHashMap
还引入了一种新的技术——无锁的 CAS 操作和 synchronized 的混合使用。通过使用 CAS、synchronized、volatile 等机制,来保证操作的原子性、可见性和有序性。这种新的实现进一步提高了 ConcurrentHashMap
的并发性能和线程安全性。
综上所述,JDK 1.8 中的 ConcurrentHashMap
通过使用 CAS 和 synchronized 机制,并放弃了之前的分段锁机制,来提供更高效和线程安全的操作。
读性能提高:
无论是1.7还是1.8,读操作都是不用加锁的,而是使用 volatile 保证变量内存的可见性
是不用加锁的,而是使用 volatile 保证变量内存的可见性