可以看到默认锁的就是本身 , 效果和Hashtable其实是一样的 。 这种简单粗暴锁整个对象的方式造成的后果是:
- 锁是非常重量级的 , 会严重影响性能 。
- 同一时间只能有一个线程进行读写 , 限制了并发效率 。
关于ConcurrentHashMap和Hashtable的更多内容 , 限于篇幅 , 我会在另一篇文章讲解 。
那么 , 使用了上述的三种解决方案是不是绝对线程安全?先观察下面的代码:
当Thread1调用containsKey之后释放锁 , Thread2获得锁并把“abc”移除再释放锁 , 这个时候Thread1读取到的s就是一个null了 , 也就出现了问题了 。 所以ConcurrentHashMap类或者
Collections.synchronizeMap()方法或者Hashtable都只能在一定的限度上保证线程安全 , 而无法保证绝对线程安全 。
关于线程安全 , 还有一个fast-fail问题 , 即快速失败 。 当使用HashMap的迭代器遍历HashMap时 , 如果此时HashMap发生了结构性改变 , 如插入新数据、移除数据、扩容等 , 那么Iteractor会抛出fast-fail异常 , 防止出现并发异常 , 在一定限度上保证了线程安全 。 如下源码:
创建Iteractor对象时会记录HashMap的modCount变量 , 每当HashMap发生结构性改变时 , modCount会加1 。 在迭代时判断HashMap的modCount和自己保存的expectedModCount是否一致即可判断是否发生了结构性改变 。
fast-fail异常只能当做遍历时的一种安全保证 , 而不能当做多线程并发访问HashMap的手段 。 若有并发需求 , 还是需要使用上述的三种方法 。
小结
- HashMap并不能保证线程安全 , 在多线程并发访问下会出现意想不到的问题 , 如数据丢失等
- HashMap1.8采用尾插法进行扩容 , 防止出现链表环导致的死循环问题
- 解决并发问题的的方案有Hashtable、Collections.synchronizeMap()、ConcurrentHashMap 。 其中最佳解决方案是ConcurrentHashMap
- 上述解决方案并不能完全保证线程安全
- 快速失败是HashMap迭代机制中的一种并发安全保证
关键变量的理解HashMap源码中有很多的内部变量 , 这些变量会在下面源码分析中经常出现 , 首先需要理解这些变量的意义 。
扩容HashMap源码中把初始化操作也放到了扩容方法中 , 因而扩容方法源码主要分为两部分:确定新的数组大小、迁移数据 。 详细的源码分析如下 , 我打了非常详细的注释 , 可选择查看 。 扩容的步骤在上述已经讲过了 , 读者可以自行结合源码 , 分析HashMap是如何实现上述的设计 。
final Node<KV>[
resize() {
// 变量分别是原数组、原数组大小、原阈值;新数组大小、新阈值
Node<KV>[
oldTab = table;
int oldCap = (oldTab == null) ? 0 : oldTab.length;
int oldThr = threshold;
int newCap newThr = 0;
// 如果原数组长度大于0
if (oldCap > 0) {
// 如果已经超过了设置的最大长度(1<<30也就是最大整型正数)
if (oldCap >= MAXIMUM_CAPACITY) {
// 直接把阈值设置为最大正数
threshold = Integer.MAX_VALUE;
return oldTab;
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
oldCap >= DEFAULT_INITIAL_CAPACITY)
// 设置为原来的两倍
newThr = oldThr << 1;
// 原数组长度为0 , 但最大限度不是0 , 把长度设置为阈值
// 对应的情况就是新建HashMap的时候指定了数组长度
else if (oldThr > 0)
newCap = oldThr;
// 第一次初始化 , 默认16和0.75
// 对应使用默认构造器新建HashMap对象
else {
newCap = DEFAULT_INITIAL_CAPACITY;
- 德尔塔|新冠病毒“最厉害变种”来袭,或从艾滋病患者体内进化而来
- 免疫系统|新冠最新毒株!比德尔塔还厉害,疫苗还管用吗?
- 飞利浦·斯塔克|MySQL统计总数就用count,别花里胡哨的《死磕MySQL系列 十》
- 飞利浦|飞利浦今年第2款智能手机上市,名为PH2线上首发价仅759元,面向百元级市场
- 科学家|?又?一变异株出现,或已攻入亚洲!科学家严厉警告,比德尔塔还可怕
- 飞利浦·斯塔克|中国广电将从五个方面推动网络建设:第四家运营商服务越来越近!
- |价值千万的核磁共振仪有多厉害?为什么我国造不出来,只能进口?
- 国际热核聚变实验堆|再冲新高,1亿摄氏度“燃烧”100秒?中国“人造太阳”有多厉害
- |最厉害的成功学是什么?
- |揭秘人体极限,来看看自己究竟有多厉害!