前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深入理解currentHashMap

深入理解currentHashMap

作者头像
IT大咖说
发布2019-12-24 12:15:42
6980
发布2019-12-24 12:15:42
举报
文章被收录于专栏:IT大咖说IT大咖说

来源:简书

1,currentHashMap的介绍

currentHashMap是线程安全并且高效的一种容器,我们就需要研究一下currentHashMap为什么既能够保证线程安全,又可以保证高效的操作

currentHashMap使用的原因

为什么使用currentHashMap,这时候我们就需要和HashMap以及HashTable进行比较 HashMap线程不安全的原因? 在多线程的情况下,HashMap的操作会引起死循环,导致CPU的占有量达到100%,所以在并发的情况下,我们不会使用HashMap. 至于为什么会引起死循环,大概是因为HashMap的Entry链表会形成链式的结构,一旦形成了Entry的链式结构,链表中的next指针就会一直不为空,这样就会导致死循环 不使用HashTable的原因? 其中使用synchronize来保证线程安全,即当有一个线程拥有锁的时候,其他的线程都会进入阻塞或者轮询状态,这样会使得效率越来越低 使用currentHashMap的锁分段技术可以有效的提高并发访问率 HashTable访问效率低下的原因,就是因为所有的线程在竞争同一把锁.如果容器中有多把锁,不同的锁锁定不同的位置,这样线程间就不会存在锁的竞争,这样就可以有效的提高并发访问效率,这就是currentHashMap所使用的锁分段技术 将数据一段一段的存储,然后为每一段都配一把锁,当一个线程只是占用其中的一个数据段时,其他段的数据也能被其他线程访问

2,currentHashMap的结构

currentHashMap是由Segment和HashEntry组成的.Segment是一种可重入的锁(Reentranlock),Segment在其中扮演锁的角色;HashEntry用于存储数据.一个CurrentHashMap包括一个Segment数组.一个Segment元素包括一个HashEntry数组,HashEntry是一种链表型的结构,每一个Segment维护着HashEntry数组中的元素,当要对HashEntry中的数据进行修改的时候,我们必须先要获得与它对应的Segment

currentHashMap的体系结构

currentHashMap

这样的话,当修改该容器的不同的段时,就不会存在并发的问题,如图可知,我们得到一个元素需要进行两次hash操作,第一次得到Segment,第二次得到HashEntry中的链表头部,这样做会使得Hash的过程比普通的HashMap要长 写操作的时候可以只对元素所在的Segment进行加锁即可,不会影响到其他的Segment,这样,在最理想的情况下,ConcurrentHashMap可以最高同时支持Segment数量大小的写操作(刚好这些写操作都非常平均地分布在所有的Segment上)

3,JDK1.8的currentHashMap的原理

JDK1.8的currentHashMap参考了1.8HashMap的实现方式,采用了数组,链表,红黑树的实现方式,其中大量的使用CAS操作.CAS(compare and swap)的缩写,也就是我们说的比较交换.CAS是一种基于锁的操作,而且是乐观锁.java的锁中分为乐观锁和悲观锁. 悲观锁是指将资源锁住,等待当前占用锁的线程释放掉锁,另一个线程才能够获取线程. 乐观锁是通过某种方式不加锁,比如说添加version字段来获取数据 CAS操作包含三个操作数-----内存位置,预期的原值,和新值.如果内存的值和预期的原值是一致的,那么就转化为新值.CAS是通过不断的循环来获取新值的,如果线程中的值被另一个线程修改了,那么A线程就需要自旋,到下次循环才有可能执行

static class Node<K,V> implements Map.Entry<K,V> {

代码语言:javascript
复制
        final int hash;
        final K key;
        volatile V val;
        volatile Node<K,V> next;

        Node(int hash, K key, V val, Node<K,V> next) {
            this.hash = hash;
            this.key = key;
            this.val = val;
            this.next = next;
        }

这是jdk1.8中的Node结点,其中的val和next都通过可见性修饰

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-12-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT大咖说 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 来源:简书
  • 1,currentHashMap的介绍
    • currentHashMap使用的原因
    • 2,currentHashMap的结构
    • 3,JDK1.8的currentHashMap的原理
    相关产品与服务
    容器服务
    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档