HashMap,HashTable,ConcurrentHashMap的实现原理及区别

一.哈希表

哈希表就是一种以 键-值(key-indexed) 存储数据的结构,我们只要输入待查找的值即key,即可查找到其对应的值。

链式哈希表从根本上说是由一组链表构成。每个链表都可以看做是一个“桶”,我们将所有的元素通过散列的方式放到具体的不同的桶中。插入元素时,首先将其键传入一个哈希函数(该过程称为哈希键),函数通过散列的方式告知元素属于哪个“桶”,然后在相应的链表头插入元素。查找或删除元素时,用同们的方式先找到元素的“桶”,然后遍历相应的链表,直到发现我们想要的元素。因为每个“桶”都是一个链表,所以链式哈希表并不限制包含元素的个数。然而,如果表变得太大,它的性能将会降低。

HashMap就是通过链式哈希表实现。

链式哈希表的其他应用场景,比如我们熟知的缓存技术(比如redis、memcached)

二.HashMap,HashTable,ConcurrentHashMap的区别

HashMap是线程不安全的,在多线程环境下,使用Hashmap进行put操作会引起死循环,因为多线程会导致HashMap的Entry链表形成环形数据结构(扩容时 ,造成next往回指),查找时会陷入死循环。,所以在并发情况下不能使用HashMap。

HashTable和HashMap的实现原理几乎一样,差别无非两点

1.HashTable不允许key和value为null

2.HashTable是线程安全的

但是HashTable线程安全的策略实现代价却太大了,简单粗暴,get/put所有相关操作都是synchronized的,这相当于给整个哈希表加了一把大锁。

多线程访问时候,只要有一个线程访问或操作该对象,那其他线程只能阻塞,相当于将所有的操作串行化,在竞争激烈的并发场景中性能就会非常差。

主要就是为了应对hashmap在并发环境下不安全而诞生的,ConcurrentHashMap避免了对全局加锁改成了局部加锁操作,极大地提高了并发环境下的操作速度,但是ConcurrentHashMap在JDK1.7和1.8中的实现非常不同。

在JDK1.7中ConcurrentHashMap采用了数组+Segment分段锁的方式实现。

ConcurrentHashMap中的分段锁称为Segment,它即类似于HashMap的结构,即内部拥有一个Entry数组,数组中的每个元素又是一个链表,ConcurrentHashMap使用分段锁技术,将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问,能够实现真正的并发访问。

优劣:

这一种结构的带来的副作用是Hash的过程要比普通的HashMap要长,ConcurrentHashMap定位一个元素的过程需要进行两次Hash操作。第一次Hash定位到Segment,第二次Hash定位到元素所在的链表的头部。

写操作的时候可以只对元素所在的Segment进行加锁即可,不会影响到其他的Segment,这样,在最理想的情况下,ConcurrentHashMap可以最高同时支持Segment数量大小的写操作(刚好这些写操作都非常平均地分布在所有的Segment上),并发能力可以大大的提高。

JDK1.8版本的ConcurrentHashMap采用了数组+链表+红黑树的实现方式来设计,内部大量采用CAS和synchronized操作。

CAS是compare and swap的缩写,即我们所说的比较交换。cas是一种基于乐观锁的操作,CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。如果内存地址里面的值和A的值是一样的,那么就将内存里面的值更新成B。如果a线程获取地址里面的值被b线程修改了,那么a线程需要自旋,到下次循环才有可能机会执行。

CAS是compare and swap的缩写,即我们所说的比较交换。cas是一种基于锁的操作,而且是乐观锁。在java中锁分为乐观锁和悲观锁。悲观锁是将资源锁住,等一个之前获得锁的线程释放锁之后,下一个线程才可以访问。而乐观锁采取了一种宽泛的态度,通过某种方式不加锁来处理资源,比如通过给记录加version来获取数据,性能较悲观锁有很大的提高。

1.数据结构:取消了Segment分段锁的数据结构,取而代之的是数组+链表+红黑树的结构。
2.保证线程安全机制:JDK1.7采用segment的分段锁机制实现线程安全,其中segment继承自ReentrantLock。JDK1.8采用CAS+Synchronized保证线程安全。
3.锁的粒度:原来是对需要进行数据操作的Segment加锁,现调整为对每个数组元素加锁(Node)。
4.链表转化为红黑树:定位结点的hash算法简化会带来弊端,Hash冲突加剧,因此在链表节点数量大于8时,会将链表转化为红黑树进行存储。
5.查询时间复杂度:从原来的遍历链表O(n),变成遍历红黑树O(logN)。

原文地址:https://www.cnblogs.com/one-apple-pie/p/10466755.html

时间: 2024-08-29 10:58:27

HashMap,HashTable,ConcurrentHashMap的实现原理及区别的相关文章

HashMap Hashtable ConcurrentHashMap 一点区别

HashMap  ConcurrentHashMap Hashtable 工作中经常会用到, HashMap用的最多, ConcurrentHashMap次之,hashTable用的最少. 简单看了下源码,其实原因还是挺明显的.从JDK的发展历程来看,hashTable是1.0就发布的,属于最早的key-value形式的存储, 到了1.2才有hashMap, ConcurrentHashMap是1.5中发布的,它们的实现有很多类同,也有很多细节上的区别.这里主要通过查看源码来比较下它们在写入与读

[Java集合] 彻底搞懂HashMap,HashTable,ConcurrentHashMap之关联.

注: 今天看到的一篇讲hashMap,hashTable,concurrentHashMap很透彻的一篇文章, 感谢原作者的分享. 原文地址: http://blog.csdn.net/zhangerqing/article/details/8193118 Java集合类是个非常重要的知识点,HashMap.HashTable.ConcurrentHashMap等算是集合类中的重点,可谓"重中之重",首先来看个问题,如面试官问你:HashMap和HashTable有什么区别,一个比较简

HashMap HashTable ConcurrentHashMap 简单比较

1. HashMap HashTable ConcurrentHashMap都是java哈希算法的实现,其中HashMap是非线程安全的,HashTable 和ConcurrentHashMap是线程安全的.单线程环境下HashMap更有速度优势. 2. HashTable 的实现方式比较简单粗暴,直接对修改操作进行加锁来控制并发访问. 3. ConcurrentHashMap,通过分段(segment)来提高并发性能,进行修改操作时,只是对相应的段进行加锁,理论上段个数的线程可以并行访问Con

HashMap\HashTable\ConcurrentHashMap的原理与区别

HashTable: 底层数组+链表,key与value都不能为null,线程安全,实现线程安全的方式是在修改数据时锁住整个HashTable,效率低. 初始size为11,扩容:newsize = oldsize*2 + 1 计算index的方法:index = (hash & 0x7FFFFFFF)%tab.length HashMap: 底层数组+链表实现,可以存储null键和null值,线程不安全 初始size为16,扩容newsize = oldsize*2,size一定为2的n次幂

JDK1.8中的HashMap.HashTable, ConcurrentHashMap有什么区别?

JDK1.8中的HashMap,HashTable,ConcurrentHashMap有什么区别? 答:HashMap是线程不安全的,底层采用数组+链表+红黑树的结构 HashTable是线程安全的,因为使用了Synchronized锁住了整个table,底层采用了数组+链表 ConcurrentHashMap是线程安全的,采用了CAS+同步锁Synchronized对链表头节点进行锁定,底层使用数组+链表+红黑树 HashMap的key和value可以是null,其他两个不行. 原文地址:ht

HhashMap HashTable ConcurrentHashMap

hashMap hashTable concurrentHashMap hashMap的效率高于hashTable,hashMap是线程不安全的,并发时hashMap put方法容易引起死循环,导致cpu利用率达到100% 所以高并发下不能使用hashMap,而是用ConcurentHashMap,则不会出现这种情况

HashMap,Hashtable,ConcurrentHashMap 和 synchronized Map 的原理和区别

HashMap 是否是线程安全的,如何在线程安全的前提下使用 HashMap,其实也就是HashMap,Hashtable,ConcurrentHashMap 和 synchronized Map 的原理和区别.当时有些紧张只是简单说了下HashMap不是线程安全的:Hashtable 线程安全,但效率低,因为是 Hashtable 是使用 synchronized 的,所有线程竞争同一把锁:而 ConcurrentHashMap 不仅线程安全而且效率高,因为它包含一个 segment 数组,将

ConcurrentHashMap以及HashMap,HashTable的区别

ConcurrentHashMap与HashMap,和HashTable 的区别? ConcurrentHashMap是一个线程安全的key-value数据结构,而HashMap不是.ConcurrentHashMap的数据结构是 数组 + 数组 + 单向链表.HashMap的数据结构是 数组 + 单向列表 HashTable也是线程安全,HashTable与HashMap的存储结构相同,HashTable不允许null为key值,而HashMap允许ConcurrentHashMap是Hash

HashMap、ConcurrentHashMap原理分析

集合(Collection)是编程中常用的数据结构,而并发也是服务器端编程常用的技术之一,并发总是离不开集合这类高级数据结构的支持.比如两个线程需要同时访问一个中间临界区(Queue),比如常会用缓存作为外部文件的副本(HashMap).而Map这种以键值对为元素的数据结构也是集合中最常用到的.Map家族中的三大类:HashMap.HashTable.ConcurrentHashMap.前者非线程安全的,后两者是线程安全的,而HashTable的实现原理与HashMap很相似,只是在公开的方法上