HashMap的实现原理

本文深入解析HashMap的实现原理,包括数据结构、put和get操作的细节,以及非线程安全的问题。此外,对比了HashTable、HashMap和ConcurrentHashMap,重点讨论了ConcurrentHashMap的分段锁策略。同时,介绍了并发包中的CAS原理及其优缺点,以及如何应对ABA问题。
摘要由CSDN通过智能技术生成

一、简介

1.HashMap的数据结构是数组+链表,因为数组:寻址容易,插入删除困难;链表:寻址困难,插入删除容易;所以结合二者优点

2.所以使用的哈希表,链表的数组,存在数组的下标,是对元素hash(key)%len获取到的

二、put的原理

1.put的时候,如果key为空,插入到数组的第一个链表;先定位数组的下标,再遍历链表,如果key存在,则替换新值,否则往该链表头插入元素;如果大小超过阈值=初始容量*加载因子,则扩容二倍;

2.如果哈希表的容量超过默认容量,将容量调整到integer.Max_Value,创建张新表,将原表映射到新表(将原数组的内容重新hash到新的扩容数组)

2.get的原理

如果key为空,取第一个数组;如果不为空,则先定位到数组元素,再遍历链表

二、HashMap的非线程安全

1.HashMap在put的时候,插入的元素超过容量,就会扩容,这个时候会将原数组的内容重新hash到新的扩容数组;在多线程的还环境下,存在同时其他的元素也在put操作,如果hash值相同,可能出现同一数组下用链表表示,造成闭环,导致get的时候出现死循环

2.在hashmap做put操作的时候会调用到以上的方法。现在假如A线程和B线程同时对同一个数组位置调用addEntry,两个线程会同时得到现在的头结点,然后A写入新的头结点之后,B也写入新的头结点,那B的写入操作就会覆盖A的写入操作造成A的写入操作丢失

三、HashTable、HashMap、ConcurentHaspMap的区别

1.HashTable:键值都不能为null,实现线程安全的方式是修改数据时,锁住整张表,效率低

2.HashMap:可以存null键null值,线程不安全

3.ConcurentHashMap:线程安全,使用分段锁,锁住的是表中的一个数组元素,效率高

四、ConcurrentHashMap的详解:使用的是分段锁

ConcurrentHashMap是由Segment数组结构和HashEntry数据结构组成;Segment是一种可重入锁ReentrantLock;一个Segment里包含一个HashEntry,每个HashEntry是一个链表的元素,所以当对HashEntry进行操作时,先获取到它对应的Segment锁;

五、了解Concurrent并发包里面的CAS原理

1.CAS是英文单词ConmareAndSwap,比较并替换

2.CAS有三个操作数:内存地址V,旧的预期值,即将更新的值

3.CAS指令执行时,当且仅当内存地址V的值与预期值相当时,将内存地址的V修改成B,否则什么都不做

4.CAS指令是原子操作,核心方法compareAndSwapInt

5.如下图,当执行CAS指定时, 没有修改成功时,一直尝试修改,这个叫自旋(AtomicInteger.getIncrement的源码)

6.i++;是非原子操作,取值,加1,写值;所以可以用AtomicInteger.getIncrement替代

7.因为这个方法必须要加1,所以有自旋。AutomicBollean.compareAndSet没有自旋,只有CAS,返回bollean,看是否执行成功

8.CAS被称为乐观锁:每次不加锁,假设没有冲突而去完成操作。如果有冲突失败就重试,值到成功。CAS原子+自旋;synchronized被称为悲观锁:这种线程一旦得到锁,其他需要锁的线程就被挂起

六、CAS的缺点

1.可以看到getAndAddInt方法执行时,如果CAS失败,会一直执行,可能会给CPU带来开销

2.只能保证一个共享变量的原子操作,多个变量只能用锁来操作

3.存在ABA问题

   3.1 内存地址读的值是A,准备赋值时,检查到它的值仍然是A,不能说它的值没有被其他线程修改过

   3.2 所以在使用CAS前要考虑ABA问题是否会影响程序并发的正确性

   3.3 针对ABA问题,JAVA并发包,提供一个带标记的原子引用类:AtomicStampedReference,通过控制变量的版本来保证CAS正确性

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值