线程进阶 --- HashMap、HashTable和ConcurrentHashMap

简介: 线程进阶 --- HashMap、HashTable和ConcurrentHashMap

一、什么是HashMap?


单线程中使用。


  • HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
  • HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。


  • HashMap 是无序的,即不会记录插入的顺序。
  • HashMap 继承于AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口。


二、什么是Hashtable?

无脑加锁版本的HashMap。不建议使用。


  • 和HashMap的基本功能一样,但是在多线程操作中,HashMap是线程不安全的,但是Hashtable是线程安全的。
  • 如果多线程访问同一个Hashtable就会直接造成锁冲突。
  • size属性也是通过synchronized来控制同步,也是比较慢的。
  • 一旦触发扩容,就又该线程完成整个扩容过程,会涉及到大量元素拷贝,效率很低

三、什么是ConcurrentHashMap?

超级优化的Hashtable。适合多线程。

相对于 Hashtable 如何进行锁策略优化的?


5edcd8accbf940b2a3de2fa9b76fe663.png


158d4f81748c48b5ad79da54e1766245.png


ConcurrentHashMap大大降低了锁的粒度。

这样每个哈希桶都有自己的一把锁就大大降低了锁竞争的概率,使代码效率大大提高。因此在多线程案例使用过程中,我们一般直接就会选择 ConcurrentHashMap。

三、相关面试题


1. ConcurrentHashMap 的读操作是否加锁?

不加锁!一般只是读操作而没有修改数据的,都不需要加锁。而是需要搭配volatile关键字,保证每次读取到的数据都是新数据。

2. 介绍下ConcurrentHashMap 的锁分段技术?


jdk1.7中使用了锁分段技术,而jdk1.8就没有再使用了,简单地说就是:

把每一个哈希桶都分成一个“段” , 而每一个段又都有一个锁,针对每个段进行加锁,就降低了锁竞争的概率,只有当两个线程访问的数据恰好在同一个 段 上的时候才会发生锁竞争。


3. ConcurrentHashMap 为什么在jdk1.8就没了?又做了怎样的优化?


jdk1.8把HashMap、ConcurrentHashMap等一些库的实现改变了:将原来的 数组+链表 的实现方式改成了 数组+链表/红黑树。当链表较长的时候(>=8个元素)就转化为了红黑树。


而在ConcurrentHashMap中 取消了分段锁,直接给每个哈希桶(即每个链表) 分配了一个锁,就是直接以每个链表的头结点作为锁对象。


4. Hashtable 和 hashMap 、ConcurrentHashMap之间的区别:


类 名称 加锁方式 key是否允许为null
HashMap

无加锁,线程不安全

允许
Hashtable 一把大锁:使用synchronized锁hashtable对象,效率较低 不允许
ConcurrentHashMap 很多小锁:使用synchronized锁每个链表的头结点,锁冲突概况低,充分利用了CAS机制,优化了扩容方式 不允许


相关文章
|
29天前
|
安全 存储 Java
HashMap和Hashtable区别是什么?
HashMap和Hashtable区别是什么?
18 4
|
2月前
|
编解码 安全 算法
Java多线程基础-18:线程安全的集合类与ConcurrentHashMap
如果这些单线程中的集合类确实需要在多线程中使用,该怎么办呢?思路有两个: 最直接的方式:使用锁,手动保证。如多个线程修改ArrayList对象,此时就可能有问题,就可以给修改操作进行加锁。但手动加锁的方式并不是很方便,因此标准库还提供了一些线程安全的集合类。
35 4
|
2月前
|
存储 安全 Java
Java容器类List、ArrayList、Vector及map、HashTable、HashMap
Java容器类List、ArrayList、Vector及map、HashTable、HashMap
20 0
|
2月前
|
存储 C++
为什么HashMap的键值可以为null,而ConcurrentHashMap不行?
为什么HashMap的键值可以为null,而ConcurrentHashMap不行?
30 1
|
2月前
|
安全 Java 调度
HashMap很美好,但线程不安全怎么办?ConcurrentHashMap告诉你答案!
HashMap很美好,但线程不安全怎么办?ConcurrentHashMap告诉你答案!
50 1
|
2月前
|
存储 缓存 安全
面试题-HashMap底层原理与HashTable的区别
字节跳动面试题-HashMap底层原理与HashTable的区别
38 0
|
2月前
|
Java
【java进阶】Java中线程的实现方式
【java进阶】Java中线程的实现方式
|
2月前
|
负载均衡 安全 算法
深入解析线程安全的Hashtable实现
深入解析线程安全的Hashtable实现
|
2月前
|
存储 Java 索引
【Java编程进阶之路 03】深入探索:HashMap的长度为什么是2的幂次方
HashMap的长度为2的幂次方是为了利用位运算快速计算索引,提高数据分散性和减少哈希冲突。这样设计能确保元素均匀分布,提高搜索效率。同时,2的幂次方长度便于动态扩容时计算新位置,简化元素迁移过程。
74 0
|
2月前
|
存储 并行计算 安全
【Java编程进阶之路 01】深入探索:HashMap、ConcurrentHashMap与HashTable的演进之路
HashMap、ConcurrentHashMap与HashTable均为Java中的哈希表实现。HashMap非线程安全但性能高,适用于单线程;HashTable线程安全但性能较低,已少用;ConcurrentHashMap线程安全且高性能,是并发环境下的首选。三者在线程安全性与性能间各有侧重。
50 1