jdk1.8的HashMap和ConcurrentHashMap学习摘要

Posted 狠一点

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jdk1.8的HashMap和ConcurrentHashMap学习摘要相关的知识,希望对你有一定的参考价值。

1、jdk1.8的HashMap设计

1.1、数据结构:数组+链表+红黑树(jdk1.6、jdk1.7采用数据+链表)


1.2、链表和红黑树的关系

当数组大小已经超过64并且链表中的元素个数超过默认设定(8个)时,将链表转化为红黑树

1.3、PUT

  • 根据key计算出hash值

  • hash值&(数组长度-1)得到所在数组的index

    • 如果该index位置的Node元素不存在,则直接创建一个新的Node

    • 如果该index位置的Node元素是TreeNode类型即红黑树类型了,则直接按照红黑树的插入方式进行插入

    • 如果该index位置的Node元素是非TreeNode类型则,则按照链表的形式进行插入操作

    • 链表插入操作完成后,判断是否超过阈值TREEIFY_THRESHOLD(默认是8),超过则要么数组扩容要么链表转化成红黑树

  • 判断当前总容量是否超出阈值,如果超出则执行扩容

     注意:jdk1.8是在链表的尾部追加,jdk1.7、jdk1.6是在链表的头部添加;

1.4、并发问题

HashMap在多线程进行扩容时可能会产生环状链表,get()时造成CPU 100%的问题。

2、jdk1.8的ConcurrentHashMap设计

2.1、数据结构:同HashMap,为高并发而设计的。

2.2、PUT

   volatile Node<K, V> [] table;

   private volatile int sizeCtl;  

  • 如果数组还未初始化,通过Unsafe的CAS操作将sizeCtl设置为-1,设置成功者,可以进行初始化操作;

  • 根据key的hash值找到对应的node,如果node==null,那么通过一个CAS原子操作来设置桶的第一个元素,失败的则继续执行插入或更新;

  • 如果node!=null,但第一个元素的hash值是-1,说明此时该桶正在进行迁移操作(又来其它线程的话,会帮着一起迁移)。 否则获取该node的锁(Synchronized)执行链表(数组大小超过64 & 链表中元素超过8转成红黑树)或者红黑树的插入或更新;

注意:jdk1.7开始大量使用CAS算法+Volatile来提升效率

2.3、SIZE(跨段操作)

jdk1.7实现方式

先尝试无锁的情况下计算最多3次的计算结果,比较两次结果一致就认为当前没有元素加入计算是准确的。否则会给每个segment加上锁,然后计算

jdk1.8实现方式
统计CounterCell[]中每个CounterCell的和,这是一个估计值,牺牲了精度来换取更高的效率。

2.4、并发度(Concurrency Level)比较

jdk1.8为node[]的大小,可变(每次数组扩容,并发度就扩大一倍),锁的是node,力度更细。

jdk1.6、jdk1.7为segment[]的大小,初始化完成之后就不变了,采用的是锁分离(分段锁)。

HashTable锁的是整个表,并发度只有1。多线程竞争时效率很低。

2.5、读为什么不需要锁?

因为对数据的读写是一个原子操作,可以不需要读锁的。但是需要保证能读到最新数据,所以必须加volatile。即数组的引用需要加volatile,同时一个Node节点中的val和next属性也必须要加volatile。

jdk1.6、jdk1.7通过两次hash可以快速找到需要的元素

jdk1.8通过链表+红黑树的形式弥补了put和get时的性能差距

jdk1.8为什么用Synchronized?之前版本用的是ReentrantLock可重入锁

AQS是API级别的。后续优化空间很小,Synchronized是JVM直接支持的,有锁粗化、锁消除、锁自旋特性,可以直接随JDK版本升级而提升

2.6、数据一致性

Jdk1.7、1.8是强一致性,写入的数据可以立马读到

Jdk1.6是弱一致性

弱一致性:put操作将一个元素加入到底层数据结构后,get可能在某段时间内还看不到这个元素



以上是关于jdk1.8的HashMap和ConcurrentHashMap学习摘要的主要内容,如果未能解决你的问题,请参考以下文章

重新认识HashMap(in JDK1.8)

jdk1.8的HashMap和ConcurrentHashMap

Java中HashMap底层实现原理(JDK1.8)源码分析

Java中HashMap底层实现原理(JDK1.8)源码分析

jdk1.8的HashMap和ConcurrentHashMap学习摘要

JDK1.8源码分析之HashMap