安信10注册_安信10娱乐平台招商【首页】hwdn521.net
安信10注册_安信10娱乐平台招商【首页】hwdn521.net
安 信 平 台 主 管 (今日更新知乎) - 的个人空间 - OSCHINA
作者:管理员    发布于:2023-06-20 06:12    文字:【】【】【

  HashTable是一个线程安全的类,它使用synchronized来锁住整张Hash表来实现线程安全,即每次锁住整张表让线程独占,相当于所有线程进行读写时都去竞争一把锁,导致效率非常低下。

  因为初始化数组完成后数组元素都还是null值,以后每一次添加一个元素的话,需要封装为entrySet对象,还需要对entrySet数组的大小重新计算,如果把第一次的计算结果全部存储到S0中,那么以后的话只需要直接拿来使用即可,不需要重新计算。虽然Segment对象不同,但是对象中属性内容其实是一样的。

  上面的源码分析了 ConcurrentHashMap 在 put 一个数据时的处理流程,下面梳理下具体流程。

  上面探究了获取 Segment 段和初始化 Segment 段的操作。最后一行的 Segment 的 put 方法还没有查看,继续分析。

  遍历 put 新元素,为什么要遍历?因为这里获取的 HashEntry 可能是一个空元素,也可能是链表已存在,所以要区别对待。

  这里面的第一步中的 scanAndLockForPut 操作这里没有介绍,这个方法做的操作就是不断的自旋tryLock()获取锁。当自旋次数大于指定次数时,使用lock()阻塞获取锁。在自旋时顺表获取下 hash 位置的 HashEntry。

  ConcurrentHashMap 的扩容只会扩容到原来的两倍。老数组里的数据移动到新的数组时,位置要么不变,要么变为 index+ oldSize,参数里的 node 会在扩容之后使用链表头插法插入到指定位置。

  有些同学可能会对最后的两个 for 循环有疑惑,这里第一个 for 是为了寻找这样一个节点,这个节点后面的所有 next 节点的新位置都是相同的。然后把这个作为一个链表赋值到新位置。第二个 for 循环是为了把剩余的元素通过头插法插入到指定位置链表。这样实现的原因可能是基于概率统计,有深入研究的同学可以发表下意见。

  算法思路:V是共享变量,我们拿着自己准备的这个E,去跟V去比较,如果E == V ,说明当前没有其它线程在操作,所以,我们把N 这个值 写入对象的 V 变量中。如果 E != V ,说明我们准备的这个E,已经过时了,所以我们要重新准备一个最新的E ,去跟V 比较,比较成功后才能更新 V的值为N。

  如果多个线程同时使用CAS操作一个变量的时候,只有一个线程能够修改成功。其余的线程提供的期望值已经与共享变量的值不一样了,所以均会失败。

  ABA问题:E和E2对比相同是不能保证百分百保证,其他线程没有在自己线程执行计算的过程里抢锁成功过。有可能其他线程操作后新E值和旧E值一样!

  ABA问题解决:在E对象里加个操作次数变量就行,每次判断时对比两个,E和操作次数就OK了,因为ABA问题中就算E相同操作次数也绝不相同

  从源码中可以发现 ConcurrentHashMap 的初始化是通过自旋和 CAS操作完成的。里面需要注意的是变量sizeCtl,它的值决定着当前的初始化状态。

  get 流程比较简单,直接过一遍源码。2023年2月28日1时26分52秒

标签:
相关推荐
  • 安信5平台主管Login(中国)科技有限公司
  • 安 信 平 台 主 管 (今日更新知乎) - 的个人空间 - OSCHINA
  • 安信3会员Login(中国)科技有限公司
  • 安信7Login(中国)股份有限公司官网
  • 安信十注册Login(中国股份)集团有限公司
  • 改名后司法集中管辖已解除 建元信托新添7宗自然人投资者诉讼纠纷
  • 【安信计算机】商用密码管理条例点评
  • 安信十注册平台
  • 【安信十注册首页】最新专家权威认证网址线路发布!
  • 安信11娱乐登录-(中国)有限公司
  • 版权所有 Copyright(C)2009-2026 安信10注册_安信10娱乐平台招商【首页】hwdn521.net TXT地图 HTML地图 XML地图
    友情链接: