1.1: ConcurrentHashMap JDK1.7结构图:数组+链表 每一个数组用一个segment作为锁,数组放值,冲突了就是链表加进去
1.2:ConcurrentHashMap JDK1.8结构图:数组+链表/红黑树 注意 如果是链表结构的 就是Node 否则会转化为 TreeNote,TreeBin封装维护好TreeNote,红黑树仿的是TreeBin,TreeBin的每个节点是TreeNote。
JDK1.7与JDK1.8之间的主要不同点:
-
数据结构不一样:1.7是数组加链表组成 1.8是数组加链表/红黑树组成
-
加锁方式不同:JDK1.7的加锁是通过一个Segment对象来对一段table进行加锁 JDK1.8是对每一个hash对应的链表或者是红黑树加锁 因此 JDK1.8更高效
锁效率比较:
synchronizedHashMap <JDK1.7 concurrenthashmap<JDK1.8 1.7concurrenthashmap
原因分析:
synchronizedHashMap <JDK1.7 concurrenthashmap :
synchronizedHashMap是在添加时对整个map进行加锁,JDK1.7concurrenthashmap有一个segment数组,通过散列方法将值散列到不同的segment数组中,加锁是对这个segment进行加锁,是对散列值相同的结果进行加锁,而不是对整体进行加锁。
JDK1.7 concurrenthashmap<JDK1.8 1.7concurrenthashmap: 1.8的效率更高。两个原因:1:也是缩小了加锁的范围,1.7加锁是对数组的一段进行加锁,1.8 取消了segment设置,进行加锁是相同的hash值进行加锁也就是链表或者红黑树。所效率加锁的范围,但是1.8还是有segment是为了兼容1.7的 2:1.8的加锁是CAS以及syn的,由于hash冲突还是比较少的,因此一般一次就成功就是 CAS操作所以速度就会快一点。
3..hash函数也不一样: 1.8的为了更加均匀的分布将1.7索要hash的对象,进行二次hash,才会放入到数组中,二次hash原理是将高8为参与运算而不是低8位进行运算
concurrenthashmap源码结构:
通过静态的代码块记载UNface类来进行CAS操作
static {
try {
U = sun.misc.Unsafe.getUnsafe();
.......
} catch (Exception e) {
throw new Error(e);
}
}
static final class MapEntry<K,V> implements Map.Entry<K,V> 内部类 ,存储每一个K-V对象。