jdk1.8之HashMap和ConcurrentHashMap

1、jdk1.8的HashMap设计

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

02113411_ryZv.jpg

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可能在某段时间内还看不到这个元素

174121_t5CT_3787772.png

ref:https://my.oschina.net/pingpangkuangmo/blog/817973

转载于:https://my.oschina.net/u/3787772/blog/1627328

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值