HashMap源码分析系列 -- 第四弹:HashMap多线程解决方案
HashMap源码分析系列 – 第五弹:HashMap的线程安全问题解决方案
从今天起,争取一周之内整理完HashMap有关的各种问题。网上有很多HashMap的源码分析的帖子,我看了一些。当然也有写的非常好的,不过大多的源码分析帖企图一篇文章就把问题讲完,有时候看起来就很混乱。而且贴了较多的源码。这里我准备分为6个部分,分别上传五篇篇博文,希望用更清晰的方式,来总结HashMap的相关问题。
六个部分
- HashMap的继承体系,HashMap的内部类,成员变量
- HashMap的常见方法的实现流程
- HashMap的一些特定算法,常量的分析
- HashMap的线程安全问题
- HashMap的线程安全问题解决方案
- HashMap1.8和1.7的区别
前言
我们知道Jdk1.7有,HashMap链表死循环问题,属于严重的BUG。那么Jdk1.8采用头插法,不会出现链表死循环的问题,那么1.8就没有线程安全问题吗?
我们知道线程安全问题会出现在修改数据的情况下,比如put,remove方法,都会出现线程安全问题。
举个例子:
两个线程A、B都在进行put操作,并且hash函数计算出的插入下标是相同的,当线程A执行完第六行代码
if ((p = tab[i = (n - 1) & hash]) == null)后由于时间片耗尽导致被挂起,而线程B得到时间片后在该下标处插入了元素,完成了正常的插入,然后线程A获得时间片,由于之前已经进行了hash碰撞的判断,所有此时不会再进行判断,而是直接进行插入,这就导致了线程B插入的数据被线程A覆盖了,从而线程不安全。
解决方案
使用并发环境安全的集合框架
Hashtable
public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, java.io.Serializable { }
简单看一下源码
我们看到,Hashtable是用synchronized关键字保证线程安全的。
强化HashMap
使用Collections工具类的synchronizedMap方法,将HashMap改造为一个线程安全的Map。
Collections.synchronizedMap(new HashMap<String,String>());
简单看一下源码
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) { return new SynchronizedMap<>(m); }
我们看到这个方法无非就是原来的方法进一步包装,多了一个synchronized关键字,和Hashtable原理一样。
ConcurretnHashMap
在ConcurrentHashMap中有个重要的概念就是Segment。我们知道HashMap的结构是数组+链表形式,从图中我们可以看出其实每个segment就类似于一个HashMap。Segment包含一个HashEntry数组,数组中的每一个HashEntry既是一个键值对,也是一个链表的头节点。在ConcurrentHashMap中有2的N次方个Segment,共同保存在一个名为segments的数组当中。可以说,ConcurrentHashMap是一个二级哈希表。在一个总的哈希表下面,有若干个子哈希表。
为什么说ConcurrentHashMap的性能要比HashTable好,HashTables是用全局同步锁,而CconurrentHashMap采用的是锁分段,每一个Segment就好比一个自治区,读写操作高度自治,Segment之间互不干扰。
Case1:不同Segment的并发写入
不同Segment的写入是可以并发执行的。
Case2:同一Segment的一写一读
同一Segment的写和读是可以并发执行的。
Case3:同一Segment的并发写入
简单看一下源码
使用大量的volatile关键字来保证可见性
remove方法
在会出现线程问题的方法也是采用synchronized关键字保证线程安全的,只不过多了一些条件判断,用"智商"换时间。
put方法
使用安全的方式使用HashMap
读写分离
- 没想好怎么写
- JDK源码系列(2)----HashMap源码分析
- Java 容器源码分析之HashMap多线程并发问题分析
- 集合系列—HashMap源码分析
- 源码分析系列1:HashMap源码分析(基于JDK1.8)
- JAVA集合源码分析系列:HashMap源码分析
- 源码分析系列1:HashMap源码分析(基于JDK1.8)
- HashMap源码分析(一):JDK源码分析系列
- HashMap源码分析(一):JDK源码分析系列
- 【Java集合学习系列】HashMap实现原理及源码分析
- java多线程系列(九)---ArrayBlockingQueue源码分析
- java多线程系列(九)---ArrayBlockingQueue源码分析
- 源码分析系列1:HashMap源码分析(基于JDK1.8)
- Java多线程系列(六)—AQS源码分析
- Java集合系列之HashMap源码分析
- HashMap源码分析(一):JDK源码分析系列
- [置顶] 40-总结-【cartographer源码分析】系列的第四部分【io源码分析】
- java1.7集合源码赏析系列:HashTable、ConcurrentHashMap、HashMap差异分析
- HashMap源码分析(一):JDK源码分析系列
- java基础系列之ConcurrentHashMap源码分析(基于jdk1.8)
- Java集合系列之HashMap源码分析