首页 > 其他分享 >HashMap非线程安全到底有什么问题

HashMap非线程安全到底有什么问题

时间:2023-07-26 20:22:30浏览次数:27  
标签:HashMap 到底 哈希 链表 线程 数组 键值

HashMap是Java中常用的数据结构,用于存储键值对,并且提供了快速的查找和插入操作。下面挖掘一下HashMap内部的架构设计思维:

哈希函数的设计:
HashMap使用哈希函数将键映射到数组索引上。好的哈希函数应该尽量减少哈希冲突,使得键能够均匀地分布在数组中,从而提高查找效率。Java中的HashMap使用了一种称为"扰动函数"(或称"混淆函数")的方式来增加哈希值的随机性,减少哈希冲突。

数组和链表的结合:
HashMap内部使用数组来存储元素,每个数组元素是一个链表或红黑树的头节点。当哈希冲突发生时,即不同的键映射到相同的数组索引上,会在链表或红黑树中形成一个桶,将多个键值对以链表或红黑树的形式存储在同一个数组位置上。

扩容和重新哈希:
HashMap在达到一定负载因子(默认是0.75)时会进行扩容,即重新创建一个更大的数组,并将原有的键值对重新哈希到新的数组中。扩容过程需要重新计算所有键的哈希值和数组索引,以保证键的均匀分布。

解决哈希冲突的方法:
当哈希冲突发生时,HashMap会采用链表或红黑树来解决。当链表长度过长时,链表会转换为红黑树,以提高查找效率。

键的唯一性:
HashMap要求键的唯一性,如果插入了具有相同哈希值但不相等的键,则会导致键的冲突,可能会导致数据覆盖或查询错误。

非线程安全的问题:
HashMap是非线程安全的数据结构,当多个线程同时对HashMap进行修改时,可能会导致数据不一致或丢失。例如,在并发环境下,一个线程在进行扩容操作,而另一个线程在插入新的键值对,可能会导致新的键值对无法插入到正确的位置,从而影响数据的正确性。

解决非线程安全问题:

使用线程安全的ConcurrentHashMap代替HashMap。
在多线程环境下,使用互斥锁来保护HashMap的修改操作,确保每次只有一个线程能够修改HashMap。
使用Collections.synchronizedMap()方法将HashMap包装成线程安全的Map。
总结:HashMap内部的设计思维包括哈希函数的设计、数组和链表的结合、扩容和重新哈希等。而HashMap非线程安全的问题主要是由于多线程同时对HashMap进行修改导致的,可以通过使用线程安全的数据结构或加锁来解决。

标签:HashMap,到底,哈希,链表,线程,数组,键值
From: https://www.cnblogs.com/DarylJi/p/17583464.html

相关文章

  • 没有人比中国人更懂 HashMap
    没有人比中国人更懂HashMap我是javapub,一名Markdown程序员从......
  • c++学习:程字辈(进程、线程、协程)
    程字辈(进程、线程、协程)介绍C++中的进程、线程、协程之间的联系及区别。(以linux下实现为例)进程概念:进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。每个进程都有自己的独立内存空间,不同进程通过进程间通信来......
  • java线程详解
    java线程详解线程概念说到线程,就不得不提进程,为什么呢,因为进程是操作系统进行分配资源和调度的最小单位,比如windows系统安装的应用软件(office、qq、微信等)启动时,由操作系统协调分配资源和调度执行称之为一个进程,进程间是相互独立和隔离的。而线程是进程最小执行单位,一个进程的......
  • java主线程等待多个子线程中任意一个有结果后,主线程继续执行
    1.背景2.代码packagecom.qianxingniwo.ls;importorg.junit.Test;importjava.util.concurrent.atomic.AtomicReference;importjava.util.concurrent.locks.LockSupport;/***@Copyright(C)XXXXX技有限公司*@Author:ldp*@Date:2023/7/2615:30*@Descri......
  • Java中代码Bug记录--泛型失效、数组删除、HashMap死循环
    最近在工作的过程中,遇到了不少奇怪自己或者同事的Bug,都是一些出乎意料的,不太容易发现的,记录一下来帮助可能也遇到了这些Bug的人1.编译时泛型校验失效Map<String,String>nameToType=newHashMap<>();nameToType.put("testName",123);//java:不兼容的类型:int无法转......
  • redis访问时的线程安全问题
    参考:https://blog.csdn.net/diweikang/article/details/90264993 Redis是线程安全的吗?Redis是个单线程程序,所以它是线程安全的。 Redis单线程为什么还能这么快?redis是基于内存的,内存的读写速度非常快redis是单线程的,避免了不必要的上下文切换和竞争条件re......
  • SpringBoot中定时任务开启多线程避免多任务堵塞
    场景SpringBoot中定时任务与异步定时任务的实现:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/117083609使用SpringBoot原生方式实现定时任务,已经开启多线程支持,以上是方式之一。除此之外还可通过如下方式。为什么SpringBoot定时任务是单线程的?查看注解@Ena......
  • Android 多线程编程 - 线程的基本使用
    1.线程的状态New:新创建状态。线程被创建,还没有调用start方法,在线程运行之前还有一些基础工作要做。Runnable:可运行状态。一旦调用start方法,线程就处于Runnable状态。一个可运行线程可能正在运行,也可能没有运行,这取决于操作系统给线程提供运行的时间。Blocked:阻塞状态。表示线程被......
  • Python time模块和datetime模块,以及多线程
    1.time模块1.1time.time()函数time.time()函数返回自1970年1月1日0点到现在的秒数。纪元时间戳可以用于剖析代码,也就是测量一段代码的运行时间。如果在代码块开始时调用time.time(),并在结束时再次打开,就可以用第二个时间戳减去第一个,得到这两次调用之间经过的时间。......
  • 线程池问题记录以及处理
    现象每天到业务高峰期就会出现提交线程被拒绝。疑问点什么原因会导致activethreads远远小于poolsize的情况下,提交任务失败关键信息线程池配置ExecutorServiceaService=newThreadPoolExecutor(130,300,60L......