当前位置: 首页 > news >正文

经典面试题:Hashtable, HashMap, ConcurrentHashMap 之间的区别

一.Hashtable

Hashtable 是 Java 早期版本(JDK 1.0)就提供的一个键值对存储的集合类。它实现了Dictionary接口,是一个线程安全的哈希表。它的键和值都不允许为null。

Hashtable是线程安全的,Hashtable通过直接在方法中加 synchronized 来保证线程安全,太过简单粗暴,在单线程比不过HashMap,在多线程比不过ConcurrentHashMap,属于上古版本的东西,现在都不用了。

二.HashMap

HashMap 是 Java 1.2 引入的一个键值对存储的集合类,它实现了Map接口。它允许null键和null值。

它不是线程安全的,但是在单线程环境下,它的性能比 Hashtable 好。

在多线程环境下线程不安全的原因:

1)多线程下扩容会死循环。JDK1.7 中的 HashMap 使用的是头插法插入元素,在多线程的环境下,扩容的时候就有可能导致出现环形链表,造成死循环。不过,JDK 8 时已经修复了这个问题,扩容时会保持链表原来的顺序。

2)多线程的 put 可能会导致元素的丢失。因为计算出来的位置可能会被其他线程的 put 覆盖。本来哈希冲突是应该用链表的,但多线程时由于没有加锁,相同位置的元素可能就被干掉了。

3)put 和 get 并发时,可能导致 get 为 null。线程 1 执行 put 时,因为元素个数超出阈值而导致出现扩容,线程 2 此时执行 get,就有可能出现这个问题。因为线程 1 执行完 table = newTab 之后,线程 2 中的 table 此时也发生了变化,此时去 get 的时候当然会 get 到 null 了,因为元素还没有转移。

三.ConcurrentHashMap

ConcurrentHashMap 是 Java 1.5 引入的一个线程安全的哈希表实现,它也是实现了Map接口。它在多线程环境下提供了高效的并发读写操作。它不允许null键和null值。

ConcurrentHashMap 在 JDK 1.7及以前使用的分段锁机制整个 Map 被分为若干段,每个段都可以独立地加锁。

ConcurrentHashMap 在JDK 1.8及以上版本使用的是桶锁(结合CAS和synchronized)。

对于读操作,通常不需要加锁,可以直接读取,ConcurrentHashMap 内部使用了 volatile 变量来保证内存可见性。

对于写操作,ConcurrentHashMap 使用 CAS 操作来实现无锁的更新,这是一种乐观锁的实现,因为它假设没有冲突发生,在实际更新数据时才检查是否有其他线程在尝试修改数据,如果有,采用悲观的锁策略,如 synchronized 代码块来保证数据的一致性。


http://www.mrgr.cn/news/60906.html

相关文章:

  • 单细胞数据分析(三):单细胞聚类分析
  • 青少年编程与数学 02-002 Sql Server 数据库应用 19课题、数据库设计实例
  • 实时监控商品信息,加速迭代优化:助力商家产品持续精进之路
  • EPLAN软件损坏或系统问题可以这样修复
  • 空天地遥感数据识别与计算——建议收藏!
  • Pytorch可视化Visdom、tensorboardX和Torchvision
  • 第J8周:Inception v1算法实战与解析
  • 智慧用电监控装置:引领0.4kV安全用电新时代
  • Linux系统解压分卷压缩文件的解决方案
  • 图解Redis 06 | Hash数据类型的原理及应用场景
  • Java与C++:比较与对比
  • 实验04while(简单循环)---7-7 斐波那契数列第n项
  • spygalss cdc 检测的bug(二)
  • Anki插件Export deck to html的改造
  • 后台管理系统的通用权限解决方案(五)SpringBoot整合hibernate-validator实现表单校验
  • Java | Leetcode Java题解之第517题超级洗衣机
  • 【每日一题】王道 - 求序列公共元素
  • 10 个重要的JavaScript概念
  • Cesium的ComputeCommand及影像投影
  • 工业互联网平台赋能制造业数字化转型方案(55页PPT)