ConcurrentHashMap 和 Hashtable 的区别&&ConcurrentHashMap线程安全的具体实现方式/底层具体实现

ConcurrentHashMap 和 Hashtable 的区别

ConcurrentHashMap 和 Hashtable 的区别主要体现在实现线程安全的方式上不同。

  • 底层数据结构:
    JDK1.7ConcurrentHashMap 底层采用 分段的数组+链表 实现,JDK1.8 采用的数据结构跟HashMap1.8的结构一样数组+链表/红黑二叉树HashtableJDK1.8 之前的 HashMap底层数据结构类似都是采用 数组+链表 的形式,数组是 HashMap 的主体链表则是主要为了解决哈希冲突而存在的
  • 实现线程安全的方式(重要):
    ① 在JDK1.7的时候,ConcurrentHashMap(分段锁) 对整个桶数组进行了分割分段(Segment)每一把锁只锁容器其中一部分数据,多线程访问容器里不同数据段的数据,就不会存在锁竞争,提高并发访问率。 到了 JDK1.8 的时候已经摒弃了Segment的概念,而是直接用 Node 数组+链表+红黑树的数据结构来实现并发控制使用 synchronized 和 CAS 来操作。(JDK1.6以后 对 synchronized锁做了很多优化) 整个看起来就像是优化过且线程安全的 HashMap,虽然在JDK1.8中还能看到 Segment 的数据结构,但是已经简化了属性,只是为了兼容旧版本
    ② Hashtable(同一把锁) :使用 synchronized 来保证线程安全,效率非常低下。当一个线程访问同步方法时,其他线程也访问同步方法,可能会进入阻塞或轮询状态如使用put 添加元素,另一个线程不能使用 put 添加元素也不能使用 get,竞争会越来越激烈,效率越低

两者的对比图:

  • HashTable:
    在这里插入图片描述
  • JDK1.7的ConcurrentHashMap:
    在这里插入图片描述
  • JDK1.8的ConcurrentHashMap(TreeBin: 红黑二叉树节点 Node: 链表节点):
    在这里插入图片描述

ConcurrentHashMap线程安全的具体实现方式/底层具体实现

JDK1.7首先将数据分为一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据时,其他段的数据也能被其他线程访问
在这里插入图片描述

  • ConcurrentHashMap 是由 Segment 数组结构HashEntry 数组结构组成。
    Segment 实现了 ReentrantLock,所以 Segment 是一种可重入锁,扮演锁的角色
    HashEntry 用于存储键值对数据一个 ConcurrentHashMap 里包含一个 Segment 数组Segment 的结构和HashMap类似,是一种数组和链表结构,一个 Segment 包含一个 HashEntry 数组,每个 HashEntry 是一个链表结构的元素每个 Segment 守护着一个HashEntry数组里的元素,当对 HashEntry 数组的数据进行修改时,必须首先获得对应的 Segment的锁

JDK1.8 的ConcurrentHashMap 取消了Segment分段锁,采用CAS和synchronized来保证并发安全。数据结构跟HashMap1.8的结构类似,数组+链表/红黑二叉树synchronized只锁定当前链表或红黑二叉树的首节点,这样只要hash不冲突,就不会产生并发,效率又提升N倍
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值