ConcurrentHashMap原理 java7 vs java8

JAVA7

在java7中,ConcurrentHashMap中核心结构是一个Segment数组,
每个Segment中都有一个HashEntry数组,也就是把一个HashMap分成
了很多个HashMap,当对ConcurrentHashMap进行操作的时候,会通过Hash计算出要操作的segment,
每一个segment都继承了ReentrantLock从而实现对segment进行加锁,保证线程安全,
同时又因为存在多个segment,减少了对同一个Segment频繁加锁的次数,提高了并发,有多少segment就能有多少并发。

JAVA8

在java8中,ConcurrentHashMap放弃了Segment,直接对Node(java8,HashEntry变成了Node)数组中元素通过synchronized进行加锁,从而将加锁的粒度变细,更加减少了冲突加锁的次数。
这样在扩容的时候,直接能将并发量提高一倍(java7的实现中,Segment是无法扩容的,只能扩容segment中的HashEntry数组)

为什么要用Synchronised呢?

  1. 假设使用可重入锁来获得同步支持,那么每个节点都需要通过继承AQS来获得同步支持。但并不是每个节点都需要获得同步支持的,只有链表的头节点(红黑树的根节点)需要同步,这无疑带来了巨大内存浪费。
  2. synchronized则是JVM直接支持的,JVM能够在运行时作出相应的优化措施:锁粗化、锁消除、锁自旋等等。这就使得synchronized能够随着JDK版本的升级而不改动代码的前提下获得性能上的提升。