iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >你可知HashMap为什么是线程不安全的
  • 328
分享到

你可知HashMap为什么是线程不安全的

HashMap线程HashMap线程不安全HashMap线程安全 2022-11-13 18:11:25 328人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

目录HashMap 的线程不安全HashMap 中的 put() 方法数据的覆盖一数据的覆盖二    HashMap 的线程不安全 HashMap 的线程不安全主

 

 

HashMap 的线程不安全

HashMap 的线程不安全主要体现在下面两个方面

  • jdk 1.7 中,当并发执行扩容操作时会造成环形链和数据丢失的情况
  • 在 jdk 1.8 中,在并发执行 put 操作时会发生数据覆盖的情况

对于 jdk 1.7 中 HashMap 的线程不安全,暂且不谈了,我们主要看看 jdk 1.8 中的

HashMap 中的 put() 方法

该 put() 方法是 jdk 1.8 中的

public V put(K key, V value) {
	return putVal(hash(key), key, value, false, true);
}

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
    node<K,V>[] tab; Node<K,V> p; int n, i;
    // 判断 table[] 是否为空,如果是空的就创建一个 table[],并获取他的长度n
    if ((tab = table) == null || (n = tab.length) == 0)
    	n = (tab = resize()).length;	
    // 如果单链表节点 Node<K,V> p == tab[i = (n - 1) & hash]) == null,
    // 就直接 put 进单链表中,说明此时并没有发生 Hash 冲突
    if ((p = tab[i = (n - 1) & hash]) == null)
    	tab[i] = newNode(hash, key, value, null);
    else {
		// 说明索引位置已经放入过数据了,已经在单链表处产生了Hash冲突
        Node<K,V> e; K k;
		// 判断 put 的数据和之前的数据是否重复
        if (p.hash == hash &&
            // 进行 key 的 hash 值和 key 的 equals() 和 == 比较,如果都相等,则初始化数组 Node<K,V> e
            ((k = p.key) == key || (key != null && key.equals(k))))   			
            e = p;
		// 判断是否是红黑树,如果是红黑树就直接插入树中
        else if (p instanceof TreeNode)
        	e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
        else {
			// 如果不是红黑树,就遍历每个节点,判断单链表长度是否大于等于 7,
			// 如果单链表长度大于等于 7,数组的长度小于 64 时,会优先选择扩容
			// 如果单链表长度大于等于 7,数组的长度大于 64 时,才会选择单链表--->红黑树
            for (int binCount = 0; ; ++binCount) {
            	if ((e = p.next) == null) {
            		// 采用尾插法,在单链表中插入数据
                	p.next = newNode(hash, key, value, null);
                	// 如果 binCount >= 8 - 1
                    if (binCount >= TREEIFY_THRESHOLD - 1) 
                    	treeifyBin(tab, hash);
                        break;
                }
				// 判断索引每个元素的key是否可要插入的key相同,如果相同就直接覆盖
                if (e.hash == hash &&
					((k = e.key) == key || (key != null && key.equals(k))))
                    break;
                 p = e;
			}
		}
		// 说明数组或者单链表中有相同的key,因此只需要将value覆盖,并将oldValue返回即可
        if (e != null) { 
        	V oldValue = e.value;
            if (!onlyIfAbsent || oldValue == null)
            	e.value = value;
                afterNodeAccess(e);
              	return oldValue;
        }
	}
	// 说明没有key相同,因此要插入一个key-value,并记录内部结构变化次数
    ++modCount;
    // 判断是否扩容
    if (++size > threshold)
    	resize();
    afterNodeInsertion(evict);
    return null;
}

数据的覆盖一

第 13 行代码是判断是否出现 hash 冲突的,假设两个线程 A、B 都在进行 put 操作,并且它们 put 数据的 key 的 hash 值是相同的,同时它们 keyA == keyB 为 true 或者 keyA.equals(keyB) 为 true,也就是说它们 put 数据的 value 是不相同的

当线程 A 执行完第 13 行代码后由于时间片耗尽导致被挂起,而线程 B 得到时间片后在该单链表处插入了元素,完成了正常的插入

然后线程 A 获得时间片,由于之前已经进行了 hash 冲突的判断,所有此时不会再进行判断,而是直接进行插入覆盖,这就导致了线程 B 插入的数据被线程 A 覆盖了,从而发生了线程不安全

数据的覆盖二

第 58 行处有个 ++size,我们这样想,还是线程 A、B,这两个线程同时进行 put 操作时,假设当前 HashMap 的 size 大小为 10

当线程 A 执行到第 58 行代码时,从主内存中获得 size 的值为 10 后准备进行 +1 操作,但是由于时间片耗尽只好让出 CPU

于是线程 B 得到 CPU 调度,还是从主内存中拿到 size 的值 10 进行 +1 操作,完成了 put 操作,并将 size = 11 写回了主内存

然后线程 A 再次得到 CPU 调度,并继续执行(此时 size 的值仍为10),当执行完 put 操作后,还是将 size = 11 写了回内存。

此时,线程 A、B 都执行了一次 put 操作,但是 size 的值只增加了 1,所有说还是由于数据覆盖又导致了线程不安全

// HashMap 中 size 变量
transient int size;

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

--结束END--

本文标题: 你可知HashMap为什么是线程不安全的

本文链接: https://www.lsjlt.com/news/169270.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 你可知HashMap为什么是线程不安全的
    目录HashMap 的线程不安全HashMap 中的 put() 方法数据的覆盖一数据的覆盖二    HashMap 的线程不安全 HashMap 的线程不安全主...
    99+
    2022-11-13
    HashMap线程 HashMap线程不安全 HashMap线程安全
  • 为什么说HashMap线程不安全
    目录1. 并发修改导致数据不一致2. 并发扩容导致死循环或数据丢失3. 非线程安全的迭代器4. 非线程安全的比较器在Java中,HashMap是一种常用的数据结构,它以键值对的形式存...
    99+
    2023-05-18
    HashMap线程不安全
  • Java基础:为什么hashmap是线程不安全的?
    原因 HashMap 是线程不安全的主要原因是它的内部结构和操作不是线程安全的。下面是一些导致 HashMap 线程不安全的因素: 非同步操作:HashMap 的操作不是线程同步的,也就是说,在多线...
    99+
    2023-09-17
    java
  • Java中为什么HashMap线程不安全
    本篇内容主要讲解“Java中为什么HashMap线程不安全”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java中为什么HashMap线程不安全”吧!01、多线程下扩容会死循环众所周知,Hash...
    99+
    2023-06-25
  • Java京东面试题之为什么HashMap线程不安全
    目录01、多线程下扩容会死循环02、多线程下 put 会导致元素丢失03、put 和 get 并发时会导致 get 到 null01、多线程下扩容会死循环 众所周知,HashMap ...
    99+
    2024-04-02
  • HashMap是线程不安全的体现有哪些
    这篇文章主要讲解了“HashMap是线程不安全的体现有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“HashMap是线程不安全的体现有哪些”吧!1.jdk1.7中的HashMap在jdk...
    99+
    2023-06-15
  • StringBuilder是线程不安全的原因是什么
    这篇文章主要介绍了StringBuilder是线程不安全的原因是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇StringBuilder是线程不安全的原因是什么文章都会有所收获,下面我们一起来看看吧。原因分...
    99+
    2023-06-27
  • java线程不安全的原因是什么
    今天就跟大家聊聊有关java线程不安全的原因是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Java可以用来干什么Java主要应用于:1. web开发;2. Android开发;...
    99+
    2023-06-14
  • ConcurrentHashMap是如何实现线程安全的你知道吗
    目录1. 前言2. ConcurrentHashMap 是如何实现线程安全的2.1. 初始化数据结构时的线程安全2.2. put 操作时的线程安全2.3. get 操作时的线程安全2...
    99+
    2022-11-13
    ConcurrentHashMap 线程安全 ConcurrentHashMap线程安全
  • java中多线程和线程安全是什么
    这篇文章给大家分享的是有关java中多线程和线程安全是什么的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。什么是进程?电脑中时会有很多单独运行的程序,每个程序有一个独立的进程,而进程之间是相互独立存在的。比如下图中...
    99+
    2023-06-25
  • 学Java线程,你不知道什么是AQS?一文带你了解Java多线程同步的灵魂
    关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。 目录 一、导读1.1 CLH锁 二、概览三、使用场景3.1...
    99+
    2023-08-17
    开发语言 面试 android 线程 java
  • C++线程安全的队列是什么
    这篇文章将为大家详细讲解有关C++线程安全的队列是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。无界队列#include<queue>#include<mutex>#inclu...
    99+
    2023-06-29
  • Python线程安全锁的作用是什么
    Python线程安全锁的主要作用是保护共享资源的访问,以防止多个线程同时访问和修改共享资源导致的数据不一致或错误。 在多线程环境中,...
    99+
    2023-10-23
    Python
  • 为什么HTTPS是安全的
    这篇文章主要介绍“为什么HTTPS是安全的”,在日常操作中,相信很多人在为什么HTTPS是安全的问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”为什么HTTPS是安全的”的疑惑有所帮助!接下来,请跟着小编一起来...
    99+
    2023-06-15
  • 告诉你为什么 ThreadLocal 可以做到线程隔离
    对于 ThreadLocal 我们都不陌生,它的作用如同它的名字——用于存放「线程本地」变量。 先通过一个小例子感受一下: private static fi...
    99+
    2024-04-02
  • Java线程安全中的原子性是什么
    本篇内容介绍了“Java线程安全中的原子性是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!何为原子性原子性:一条线程在执行一系列程序指令...
    99+
    2023-07-05
  • Java线程安全中的有序性是什么
    这篇文章主要介绍了Java线程安全中的有序性是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java线程安全中的有序性是什么文章都会有所收获,下面我们一起来看看吧。什么是有序性在开发中,我们通常按照从上到下...
    99+
    2023-07-05
  • Java多线程高并发中解决ArrayList与HashSet和HashMap不安全的方案
    1.ArrayList的线程不安全解决方案 将main方法的第一行注释打开,多执行几次,会看到如下图这样的异常信息:👇👇👇 这是一个...
    99+
    2024-04-02
  • java的SimpleDateFormat线程不安全怎么办
    这篇文章主要为大家展示了“java的SimpleDateFormat线程不安全怎么办”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“java的SimpleDateFormat线程不安全怎么办”这篇...
    99+
    2023-06-20
  • 你知道吗?Python 响应 Django 教程可以让你的网站更加安全!
    随着互联网技术的不断发展,越来越多的网站开始使用Python语言和Django框架来开发网站。Python和Django具有简单易学、高效稳定等优点,而且可以帮助开发者更快地构建安全可靠的网站。在本文中,我们将介绍如何使用Python和D...
    99+
    2023-11-15
    响应 django 教程
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作