电面突然被问到这个问题,之前看到过,但是印象不深,导致自己没有答出来,现在总结一下。

HashMap的内部存储结构

transient Node<K,V>[] table;

static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
}

  使用了一个Node数组,这个Node数组的默认大小为16,所有hash值相同的key会存储到同一个链表中,HashMap的构成大概是这个样子(数组、链表、红黑树)

  

    知道了hashmap的实现原理,那么再来谈一谈HashMap的自动扩容机制,默认的Node数组大小为16,如果有特别多的元素,比如说100万个元素,那么最优的情况下,每个hash桶有100万/16=62500个元素,那对于这么多元素来说,存取难度会增加,为了解决这个问题,加入了自动扩容机制。

    说到自动扩容机制,首先要知道一些字段

    int threshold;             // 所能容纳的key-value对极限
final float loadFactor; // 负载因子
int modCount;
int size;

    threshold是HashMap所能容纳的最大数据量的Node个数,loadFactor是负载因子,modCount用来记录HashMap内部结构发生变化的次数,size是记录实际存在的键值对数量。这里面,threshold=loadFactor*length,这个length是数组长度,当HashMap中元素超过threshold值的话,就发生自动扩容,例如初始的Node长度为16,负载因子为默认的0.75,那么如果元素个数超过了16*0.75=12的话,就会引发自动扩容,Node自动扩展为原来的两倍

    那为什么HashMap线程不安全呢?

      一、如果多个线程同时使用put方法,当key值一样时,可能会发生覆盖

      二、如果多个线程同时检测到元素个数超过了loadFactor*数组大小,那么就会发生多个线程同时对Node数组进行扩容,都重新计算元素位置以及复制数据,但最终只有一个线程扩容后的数组会赋给table,那么其他线程的都会丢失,并且各自线程put的数据也会丢失。

      HashMap在并发执行put操作的时候会引起死循环,导致CPU利用率接近100%,多线程会导致HashMap的Node链表行程环形数据结构,一旦行程环形数据结构,Node的next节点永远不为空,会在获取Node时产生死循环。

为什么HashMap不是线程安全的的更多相关文章

  1. 牛客网Java刷题知识点之为什么HashMap不支持线程的同步,不是线程安全的?如何实现HashMap的同步?

    不多说,直接上干货! 这篇我是从整体出发去写的. 牛客网Java刷题知识点之Java 集合框架的构成.集合框架中的迭代器Iterator.集合框架中的集合接口Collection(List和Set). ...

  2. 验证HashSet和HashMap不是线程安全

    JAVA集合类: java.util包下的HashSet和HashMap类不是线程安全的, java.util.concurrent包下的ConcurrentHashMap类是线程安全的. 写2个测试 ...

  3. 一次电话Java面试的问题总结(JDK8新特性、哈希冲突、HashMap原理、线程安全、Linux查询命令、Hadoop节点)

    面试涉及问题含有: Java JDK8新特性 集合(哈希冲突.HashMap的原理.自动排序的集合TreeSet) 多线程安全问题 String和StringBuffer JVM 原理.运行流程.内部 ...

  4. HashMap和Hashtable 线程安全性

    HashMap和Hashtable的比较是Java面试中的常见问题,用来考验程序员是否能够正确使用集合类以及是否可以随机应变使用多种思路解决问题.HashMap的工作原理.ArrayList与Vect ...

  5. HashMap为什么是线程不安全的

    HashMap底层是一个Entry数组,当发生hash冲突的时候,hashmap是采用链表的方式来解决的,在对应的数组位置存放链表的头结点.对链表而言,新加入的节点会从头结点加入. 我们来分析一下多线 ...

  6. (转载)两种方法让HashMap线程安全

    HashMap不是线程安全的,往往在写程序时需要通过一些方法来回避.其实JDK原生的提供了2种方法让HashMap支持线程安全. 方法一:通过Collections.synchronizedMap() ...

  7. HashMap非线程安全分析

    通过各方资料了解,HashMap不是线程安全的,但是为什么不是线程安全的,在什么情况下会出现问题呢? 1. 下面对HashMap做一个实验,两个线程,并发写入不同的值,key和value相同,最后再看 ...

  8. hashmap,hashTable concurrentHashMap 是否为线程安全,区别,如何实现的

    线程安全类 在集合框架中,有些类是线程安全的,这些都是jdk1.1中的出现的.在jdk1.2之后,就出现许许多多非线程安全的类. 下面是这些线程安全的同步的类: vector:就比arraylist多 ...

  9. HashMap线程不安全的体现

    前言:我们都知道HashMap是线程不安全的,在多线程环境中不建议使用,但是其线程不安全主要体现在什么地方呢,本文将对该问题进行解密. 1.jdk1.7中的HashMap 在jdk1.8中对HashM ...

随机推荐

  1. PyQt5--ShowTips

    # -*- coding:utf-8 -*- ''' Created on Sep 13, 2018 @author: SaShuangYiBing ''' import sys from PyQt5 ...

  2. 配置好jdk后,cmd编写java -version还是报找不到jdk

    找了好长时间没查出问题在哪,配置的都没有问题,最后搜了搜网上发现,jdk的这两行得在最上面才行.

  3. MySql详解(四)

    MySql详解(四) MySql的DML操作 插入: 一.方式一 语法: insert into 表名(字段名,...) values(值,...); 特点: 1.要求值的类型和字段的类型要一致或兼容 ...

  4. 关于ARMv8指令的几个问题

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/qianlong4526888/article/details/27512629 NOTE:下面内容仅 ...

  5. ubuntu 中安装 ZED SDK 及结合ROS 的使用

    双目视觉(stereo vision),由于估计深度相对容易且稠密,在姿态估计和建图时容易初始化和估计尺度,所以在三维重建,SLAM等的应用中有这广泛的应用. ZED 作为近几年出现的商业化双目传感器 ...

  6. 1、JUC--volatile 关键字-内存可见性

    Java JUC简介 在 Java 5.0 提供了 java.util.concurrent (简称JUC )包,在此包中增加了在并发编程中很常用的实用工具类,用于定义类似于线程的自定义子系统,包括线 ...

  7. connection reset by peer问题总结及解决方案

    找遍了 中英文网站,翻遍了能找的角落,发现了出现故障的原因和原理,及改如何处理,这里记录下,希望能帮助到有需要的小伙伴,少走点弯路, 以上就整理内容: connection reset by peer ...

  8. C#游戏开发中快速的游戏循环

    C#游戏开发中快速的游戏循环的实现.参考<精通C#游戏编程>一书. using System; using System.Collections.Generic; using System ...

  9. scrollIntoView()的用法

    scrollIntoView是一个与页面(容器)滚动相关的API(官方解释),该API只有boolean类型的参数能得到良好的支持(firefox 36+都支持),所以在这里只讨论参数Boolean类 ...

  10. day41

    今日内容: 1.完整查询语句 2.多表查询 3.子查询 1.完整查询语句: 首先对于昨天的学习补充一个复制表 示例:首先我在一个库中创建了一个t1表(id 为int类型 设置为主键 并且设置了自增描述 ...