首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

一文读懂JAVA并发容器类ConcurrentHashMap

上文说了HashMap,其实HashMap是线程非安全的,JDK里面有个线程安全的就是HashTable,查看HashTable每个方法都增加了synchronized同步锁,也就说每次只能进入一个线程,这样影响效率。JDK源码也推荐使用ConcurrentHashMap。

推理ConcurrentHashMap的实现1.8

JDK的描述

如果你不需要线程安全,那么使用HashMap,如果需要线程安全,那么使用ConcurrentHashMap。HashTable已经被淘汰了,不要在新的代码中再使用它。

描述

和 HashMap 非常类似,唯一的区别就是其中的核心数据如 value ,以及链表都是 volatile 修饰的,保证了获取时的可见性。原理上来说:根据 key 计算出 hashcode ,判断是否需要进行初始化,f 即为当前 key 定位出的 Node,如果为空表示当前位置可以写入数据,利用 CAS 尝试写入,多个线程操作只有一个成功,失败则自旋保证成功。如果当前位置的 hashcode == MOVED == -1,则需要进行扩容。如果都不满足,则利用 synchronized 锁写入数据。,如果数量大于 TREEIFY_THRESHOLD 则要转换为红黑树。。Mysql里面有表锁和行锁的概念。表锁就是HashTable,行锁就是ConcurrentHashMap 。

JDK1.8中的ConcurrentHashMap原理分析

1.7 已经解决了并发问题,并且能支持 N 个 Segment 这么多次数的并发,但依然存在 HashMap 在 1.7 版本中的问题。那么是什么问题呢?很明显那就是查询遍历链表效率太低。

因此 1.8 做了一些数据结构上的调整。,在 JAVA8 中它摒弃了 Segment(锁段)的概念,而是启用了一种全新的方式实现,利用 CAS 算法。底层依然由“数组”+链表+红黑树的方式思想,但是为了做到并发,又增加了很多辅助的类,例如 TreeBin、Traverser等对象内部类。如何让多线程之间,对象的状态对于各线程的“可视性”是顺序一致的:ConcurrentHashMap 使用了 happensbefore 规则来实现。happens-before规则(摘取自 JAVA 并发编程):

程序次序法则

线程中的每个动作A都 happens-before 于该线程中的每一个动作B,其中,在程序中,所有的动作B都能出现在A之后。

监视器锁法则

对一个监视器锁的解锁 happens-before 于每一个后续对同一监视器锁的加锁。

volatile 变量法则

对 volatile 域的写入操作 happens-before 于每一个后续对同一个域的读写操作。

线程启动法则

在一个线程里,对 Thread.start 的调用会 happens-before 于每个启动线程的动作。

线程终结法则

线程中的任何动作都 happens-before 于其他线程检测到这个线程已经终结、或者从 Thread.join 调用中成功返回,或 Thread.isAlive 返回 false。

中断法则

一个线程调用另一个线程的 interrupt happens-before 于被中断的线程发现中断。

终结法则

一个对象的构造函数的结束 happens-before 于这个对象 finalizer 的开始。

传递性

如果 A happens-before 于 B,且 B happens-before 于 C,则 A happens-before于C:

假设代码有两条语句,代码顺序是语句1先于语句2执行;那么只要语句之间不存在依赖关系,那么打乱它们的顺序对最终的结果没有影响的话,那么真正交给CPU去执行时,他们的执行顺序可以是先执行语句2然后语句1。

PS:不管是1.7的hashMap还是ConcurrentHashMap,源码的可读性变差。目前基本都是jdk1.8就没有说1.7的事情,毕竟事务都是在进化的。里面用到了很多数据结构,数据结构说难也不难,说容易也不容易,它本身就是人的思维的一种体现。好像说走路方式一样,怎么走都可以到指定的地方,但是方法不一样,数据结构就是通过更加科学方式来进行,归根到底还是看我的【数据结构与算法】专题。数据结构给你,通过算法来进行查找,如果是遍历的方式来查,可能相对于hash的形式要差一些。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200925A0F6AN00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券