在多线程环境下使用哈希表

简介: 在多线程环境下使用哈希表

一.HashTable和HashMap

HashTable是JDK1.0时创建的,其在创建时考虑到了多线程情况下存在的线程安全问题,但是其解决线程安全问题的思路也相对简单:

5ac4c4b20b1753f0748c469cd094b4bc.png

在其众多实现方法上加上synchronized关键字(效率较低),保证其串行化执行。


但是随着业务场景的多样化,在单线程情况下不需要考虑线程安全问题,于是HashMap应运而生,同理,hashMap没有办法保证线程安全,后面随着多线程情况中的线程安全问题需求不断扩大,在多线程环境下使用哈希表有了新的解决方案。


二.JUC包下的ConcurrentHashMap


我们在这再详细说一下Hashtable存在的弊端:对整个hashtable对象加同一把锁,在多线程情况下,任意两个线程访问Hashtable中的任意数据都会产生锁竞争, size属性也是通过synchronized进行同步的,也是比较慢。同时,一旦触发扩容,该线程完成整个扩容,这个过程涉及到大量元素的拷贝,效率比较低。


ConcurrentHashMap针对这些方面进行了一系列的优化:在读时不加锁,这样大大提高了在hashmap中读取元素的效率,但是需要在元素上加volatile关键字,保证在其元素修改后能第一时间获取,只在写操作上加锁,而且它的加锁方式并不是对整个hashmap对象加锁,而是对‘桶’加锁:对hash表中的每个下标(链表头结点作为锁对象)(提高了锁密度),大大降低了锁冲突的概率。



图示就是由上面这种转化为下面这种

758d1d7508e782d7c5538fa817142409.png

407b2dcafb420bd0c4f7b2208f7ed613.png

同时利用CAS的特性对size进行更新,效率提高


与此同时还优化了元素的更新策略:化整为零,在进行扩容时,将旧桶中的部分元素搬运到新桶中,在以后调用新桶的方法时再每次搬运部分元素,在这个过程中添加新的元素时直接往新桶中添加,在查找时在两个桶中都进行查找,直到搬运完最后一个元素,再将老桶删除掉(新桶和老桶会同时存在一段时间)


最后我们提出一个问题


concurrentHashMap和HashMap、HashTable之间的区别


①HashMap是线程不安全的


②HashTable线程安全,但是不推荐使用,因为所有的操作都加了synchronized关键字,对性能影响比较大


③ConcurrentHashMap的锁粒度小,不是对整个hash表进行加锁,而是对每一个数据的下标进行加锁


④ConcurrentHashMap对于put()加锁,对于读get()不加锁


⑤对于大量共享变量运行了volatile关键字修饰


⑥对ConcurrentHashMap对扩容进行了优化

9dd3c7aad18e5cb1d22ea75045680121.png


相关文章
|
3月前
|
缓存 Java 容器
多线程环境中的虚假共享是什么?
【8月更文挑战第21天】
32 0
|
3月前
|
Cloud Native Java 调度
项目环境测试问题之线程同步器会造成执行完任务的worker等待的情况如何解决
项目环境测试问题之线程同步器会造成执行完任务的worker等待的情况如何解决
|
4月前
|
设计模式 安全 Java
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
78 1
|
4月前
|
设计模式 安全 Java
Java面试题:如何实现一个线程安全的单例模式,并确保其在高并发环境下的内存管理效率?如何使用CyclicBarrier来实现一个多阶段的数据处理任务,确保所有阶段的数据一致性?
Java面试题:如何实现一个线程安全的单例模式,并确保其在高并发环境下的内存管理效率?如何使用CyclicBarrier来实现一个多阶段的数据处理任务,确保所有阶段的数据一致性?
62 0
|
4月前
|
设计模式 并行计算 安全
Java面试题:如何使用设计模式优化多线程环境下的资源管理?Java内存模型与并发工具类的协同工作,描述ForkJoinPool的工作机制,并解释其在并行计算中的优势。如何根据任务特性调整线程池参数
Java面试题:如何使用设计模式优化多线程环境下的资源管理?Java内存模型与并发工具类的协同工作,描述ForkJoinPool的工作机制,并解释其在并行计算中的优势。如何根据任务特性调整线程池参数
50 0
|
4月前
|
存储 安全 Java
Java面试题:假设你正在开发一个Java后端服务,该服务需要处理高并发的用户请求,并且对内存使用效率有严格的要求,在多线程环境下,如何确保共享资源的线程安全?
Java面试题:假设你正在开发一个Java后端服务,该服务需要处理高并发的用户请求,并且对内存使用效率有严格的要求,在多线程环境下,如何确保共享资源的线程安全?
69 0
|
4月前
|
存储 安全 Java
Java面试题:请解释Java内存模型,并说明如何在多线程环境下使用synchronized关键字实现同步,阐述ConcurrentHashMap与HashMap的区别,以及它如何在并发环境中提高性能
Java面试题:请解释Java内存模型,并说明如何在多线程环境下使用synchronized关键字实现同步,阐述ConcurrentHashMap与HashMap的区别,以及它如何在并发环境中提高性能
39 0
|
4月前
|
存储 安全 Java
Java面试题:如何在Java应用中实现有效的内存优化?在多线程环境下,如何确保数据的线程安全?如何设计并实现一个基于ExecutorService的任务处理流程?
Java面试题:如何在Java应用中实现有效的内存优化?在多线程环境下,如何确保数据的线程安全?如何设计并实现一个基于ExecutorService的任务处理流程?
46 0
|
4月前
|
安全 Java 调度
Java面试题:Java内存优化、多线程安全与并发框架实战,如何在Java应用中实现内存优化?在多线程环境下,如何保证数据的线程安全?使用Java并发工具包中的哪些工具可以帮助解决并发问题?
Java面试题:Java内存优化、多线程安全与并发框架实战,如何在Java应用中实现内存优化?在多线程环境下,如何保证数据的线程安全?使用Java并发工具包中的哪些工具可以帮助解决并发问题?
62 0