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

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. 技术分享之AQS——内容提要

    1. 背景 最近团队内部技术分享,我做了个关于AQS的分享.ppt中涵盖的部分要点内容,现在整理到博客上. 关于AQS本身的源码解读,可以参考我之前的博文. 2. 要点梳理 下面是一些技术分享的要点梳 ...

  2. Volley源码分析(四)NetWork与ResponseDelivery工作原理

    这篇文章主要分析网络请求和结果交付的过程. NetWork工作原理 之前已经说到通过mNetWork.performRequest()方法来得到NetResponse,看一下该方法具体的执行流程,pe ...

  3. 【转】默认网关有什么用?我应当怎么填写默认网关和DNS呢

    默认网关有什么用?我应当怎么填写默认网关和DNS呢? 目前使用的是pppoe方式上网,无猫,只是将一根入户的网线插在无线路由上面,然后在路由中设置ppoe方式上网,输入帐号密码.一般电脑和手机全设成了 ...

  4. 关于JRebel启动tomcat访问上次工程的index.jsp

    检查了一下,原来我把上次配置文件包括JRebel配置文件一起复制过来,用JRebel启动时tomcat访问JRebel配置文件的目录下 这个是我上次文件的路径,把JRebel配置文件删除了,然后 di ...

  5. [Java123] JBoss

    https://blog.csdn.net/taogebx/article/details/4620760

  6. Win10环境Tensorflow-GPU13.1/JupyterNotebook的安装

    参考 : Anaconda Tensorflow GPU 版本的安装问题 https://blog.csdn.net/u010977034/article/details/62038698 Windo ...

  7. ping和telnet

    ping命令 验证IP的可达性 本地ping虚拟机中的ip地址: telnet命令 验证服务的可用性,某个端口是否打开 连接到服务器的端口上: 几种场景: (1)ping通,telnet不行 ip地址 ...

  8. CentOS配置Hive

    hive搭建共分为三种模式:1.embedded,2.local,3.remote server 在这里,主要是配置第3种模式:remote server模式,如下图所示: 我的环境共三台虚拟机:Ho ...

  9. Leetcode——338. 比特位计数

    题目描述:题目链接 对于求解一个十进制数转化为二进制时里面1的个数,可以先看一下概况: 十进制数 二进制数 1的个数 1 1    1 2 10 1 3 11   2 4 100 1 5 101 2 ...

  10. Oracle 批量修改某个用户下表的表空间

    说明:一般来说要修改表的表空间需要同时修改表的表空间和其对应的索引表空间,并且在修改含有BOLB字段的表的表空间时又不一样,具体请参考末尾的链接 思路:拼凑一个满足条件的批处理查询语句,将查询的结果复 ...