ConcurrentHashMap原理及jdk7和jdk8的区别
jdk7:
- 数据结构:
ReentrantLock+Segment+HashEntry,一个Segment中包含一个HashEntry数组,每个HashEntry又是一个链表结构
- 元素查询:
二次hash,第一次Hash定位到Segment,第二次Hash定位到元素所在的链表的头部
- 锁:
Segment分段锁 Segment继承了ReentrantLock,锁定操作的Segemnt,其他的Segment不受影响,并发度为segment个数,可以通过构造函数指定,数组扩容不会影响到其他的Segment
- get方法无需加锁,volatile保证。
jdk8:
- 数据结构:
synchronized+CAS+Node+红黑树,Node的val和next都用volatile修饰,保证可见性
- 元素查询,替换,复制操作都使用CAS。
- 锁:锁链表的head节点,不影响其他元素的读写,锁粒度更细,效率更高,扩容时,阻塞所有的读写操作、并发扩容
- 读操作无锁:
- Node的val和next使用volatile修饰,读写线程对该变量互相可见。
- 数组用volatile修饰,保证扩容时被读线程感知
CAS
https://segmentfault.com/a/1190000014858404
CAS 全称是 compare and swap,是一种用于在多线程环境下实现同步功能的机制。CAS 操作包含三个操作数 -- 内存位置、预期数值和新值。CAS 的实现逻辑是将内存位置处的数值与预期数值想比较,若相等,则将内存位置处的值替换为新值。若不相等,则不做任何操作。
在 Java 中,Java 并没有直接实现 CAS,CAS 相关的实现是通过 C++ 内联汇编的形式实现的。Java 代码需通过 JNI 才能调用。关于实现上的细节,我将会在第3章进行分析。
前面说了 CAS 操作的流程,并不是很难。但仅有上面的说明还不够,接下来我将会再介绍一点其他的背景知识。有这些背景知识,才能更好的理解后续的内容。