ConcurrentHashMap面试
CAS 自旋操作
CAS是compare and swap的缩写,即我们所说的比较交换。cas是一种基于锁的操作,而且是乐观锁。在java中锁分为乐观锁和悲观锁。悲观锁是将资源锁住,等一个之前获得锁的线程释放锁之后,下一个线程才可以访问。而乐观锁采取了一种宽泛的态度,通过某种方式不加锁来处理资源,比如通过给记录加version来获取数据,性能较悲观锁有很大的提高。乐观锁适用于读多写少的情况下面。
CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。如果内存地址里面的值和A的值是一样的,那么就将内存里面的值更新成B。CAS是通过无限循环来获取数据的,若果在第一轮循环中,a线程获取地址里面的值被b线程修改了,那么a线程需要自旋,到下次循环才有可能机会执行。
CAS 存在的问题:
存在的问题: ABA 问题,一个线程将数值 a 改成 b,然后又改成了 a,CAS 是认为没有变化的,其实已经变化了,解决方案加一个版本号。每次操作的时候 version+1.
CPU 利用率增加,CAS 的无限循环判断过程中,如果线程一直没有获取到状态,CPU 资源一直被占用。
ConcurrentHashMap
这个需要和 HashMap 进行比较。
对于 Node 数组,使用 volatile 关键字修饰,防止指令重排序发生。
put 方法进入一个死循环,进行 CAS 操作
ConcurrentHashMap 的 get 方法是不加锁的,table 使用了 volatile 关键字修饰,保证了每次获取的值都是最新的。
concurrenthashmap 是线程安全的容器,在并发情况下面是线程安全的。而 HashMap 是不安全的
允许null 值吗?
HashMap 是允许 null 值的。hashMap 允许一个 key 是 null 值,value 可以允许多个 null 值。
而 currentHashMap 是不允许 null 值的,因为 null 值有两种情况,一个是不存在,还有一个 value 就是 null,有些场景下面 value 就是 null,存在 key 的。那这样就会出现了歧义。
面试题
cuncurrentHashMap 的 get 方法是否需要加锁,为什么?
cuncurrentHashMap 和 HashMap 的区别是什么?
cuncurrentHashMap 在 jdk1.7 和 1.8 的结构分别是什么?做了什么修改
参考:https://blog.csdn.net/u011381576/article/details/79922538
#HashMap##ConcurrentHashMap面试#牛牛的面试专栏,希望自己在25年可以拿到一份大厂的SP Offer 你的点赞和收藏都是我持续更新的动力