HashMap AND ConcurrentHashMap AND Hashtable:

HashMap:

HashMap: 数组 + 链表 /红黑树(链表升级为红黑树条件:当链表长度大于8,数组长度大于64; 红黑树降级为链表条件: 当红黑树高度小于6)

(非线程安全的容器)

  • JDK1.7 死循环
  • JDK1.8 数据覆盖

JDK1.7死循环分析:
在这里插入图片描述
JDK1.7 之所以死循环原因是 resize()中的transfer()方法导致:如下
在这里插入图片描述

ConcurrentHashMap:

(下图来源于网络)
在这里插入图片描述

(线程安全的容器)

ConcurrentHashMap使用分段锁技术(Segment),将数据分成一段一段的存储,然后给每一段数据配一把锁(悲观锁),当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问,能够实现真正的并发访问。
在这里插入图片描述
分段锁:
(下图来源于网络)
在这里插入图片描述

JDK1.8锁优化:

**ConcurrentHashMap 取消了 Segment 分段锁,采用CAS 和 synchronized 来保证并发安全。**数据结构跟 HashMap1.8 的结构类似,数组+链表/红黑二叉树。Java 8 在链表场度超过一定阈值(8)时将链表(寻址时间复杂度为 O(N))转换为红黑树(寻址时间复杂度为 O(log(N))) synchronized 只锁定当前链表或红黑二叉树的盲节点,这样只要 hash 不冲突,就不会产生并发,效率又提升 N 倍。

Hashtable:

(线程安全的容器)

给put方法整体加锁,因此一般情况下不会使用Hashtable。
在这里插入图片描述

面试题: HashMap, Hashtable,ConcurrentHashMap 的区别?

  1. HashMap是非线程安全的容器,它在 JDK 1.7会造成死循环,JDK 1.8会造成数据覆盖;Hashtable和ConcurrentHashMap都是线程安全。

  2. Hashtable 实现线程安全的手段比较简单,它是在 put方法整体加了一把锁,使用synchronized 修饰,因此性能不高,所以使用频率比较低;ConcurrentHashMap是 HashMap在多线程下的替代方案,它在 JDK 1.7的时候使用的 Lock 加分段锁的方案来实现线程安全问题的保障的,而在JDK 1.8 的时候使用了大量的CAS,volatile 来实现线程的,并且在 JDK 1.8 的时候读取的时候不加锁(读取的数据可能不是最新,因为读取和写入可以同时进行),只有在写的时候才加锁。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值