ConcurrentHashMap进阶面试题

ConcurrentHashMap 1.8的优化

  1. 存储的时候的优化
  2. 写数据的时候加锁的优化
  3. 扩容时的优化,有一个协助扩容的概念
  4. 计数器的优化,在记录元素个数时,使用的类似与longAdder的形式,不会过度消耗CPU资源
    在这里插入图片描述
    为什么多线程情况下longAdder会比atomic性能优化?
 AtomicLong VS LongAdder
 LongAdder适合的场景是统计求和计数的场景
 在竞争激烈的情况下,LongAdder的效率比AtomicLong高,但要消耗更多的空间
 
 LongAdder 性能优势
 LongAdder 的基本思路是分散热点,
 AtomicLong 中存在成员变量 value 保存 long 值,在高并发的情况下该 value 值是一个热点,由 N 个线程竞争;
 LongAdder 将 value 值分散到一个数组中,不同的线程命中到数组的不同的槽中,
 各线程仅仅对自己槽中的值进行 CAS 操作,从而分散热点减少冲突

ConcurrentHashMap 为什么使用散列算法

  1. 可以让key的hash的高位和低位都参与到计算当中,与右移16位后的本身做异或运算是为了让高16位也参与运算,使得结果更加的随机,不然基本大多数情况只有低位参与运算。而之所以选择异或运算,是因为,异或运算的结果更平均,例如1和0做异运算,(1和1,1和0,0和1,0和0)4种情况有3种结果是0,一种是1。或运算则1种结果为1,3种为0。而异或运算是2种结果为1,2种结果为0.更平均。 更加的随机+更加的平均 + 没有负数???
    在这里插入图片描述

ConcurrentHashMap 初始化数组的流程

  1. sizeCtl这个属性是数组在初始化和扩容操作时的一个控制变量
  2. 在初始化数组的时候,用了DCL的概念,先判断了数组初始化了没有,如果正在初始化,会通过Thread.yield()让出CPU资源,如果么有初始化,会通过cas修改sizeCtl,判断数组初始化了没有,没有的话再次初始化数组

在这里插入图片描述

ConcurrentHashMap 扩容的流程

  1. 确认什么时候会触发扩容
  2. 触发扩容的时候,计算扩容标识戳
  3. 计算扩容标识戳的时候,会先往左诺16位+2代表是第一个进来扩容的线程
  4. 当线程扩容开始之后,要计算每个线程迁移数据的最小长度是多少,最小值是16
  5. 计算完扩容的长度之后,要初始化一个新的数组
  6. 初始化数组之后,领取任务,从xxx索引未知开始迁移,把老数组数据迁移到新数组之中
  7. 迁移完成之后,看是不是最后一个线程迁移完成的,如果是最后一个线程迁移完成的话,要从头到位检查一下有没有遗漏的数据

ConcurrentHashMap 读取数据的流程

  1. get方法是不会加锁的,查询时,第一步,基于Key得到hashcode值,再基于hashcode定位到索引的某一个未知,如果数组上存储的数据就是我要的,直接返回,如果数组上的数据不是我要的
  2. 我可能做两布查询
    第一种情况,查询双向链表,在链表中next查询,时间复杂度为oN
    另一种情况,如果数据做了迁移,下面是红黑树,那么会基于find方法做其他查询,如果数据已经迁移了,会直接查询新数据nexttable,在nexttable中查询
  3. 如果是红黑树,在红黑树里面,如果有写操作正在执行,或者有写操作正在等待,读操作会查询双向链表,如果没有写操作在执行,也没有写操作在等待
    就直接查询红黑树,以二分半的形式,以大O的logN的时间复杂度去查询需要的数据

ConcurrentHashMap addcount(计数器的实现)

  1. 类似与使用了longAdder实现了这部分功能,并发不高的情况下使用baseCount进行cas,并发高的时候使用CounterCell数组,对CounterCell中的value进行cas操作
  2. size()方法,用了countercell数组中的value和baseCoune相加返回的
  3. size()是弱一致性,不是强一致性
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一些可能被问到的concurrentHashmap面试题: 1. 什么是ConcurrentHashMapConcurrentHashMapJava中的一个线程安全的哈希表。它是由多个分离的桶组成的,每个桶都可以被独立地锁住,从而使得多个线程可以同时访问不同的桶,从而提高了并发性能。 2. ConcurrentHashMap与HashMap有什么区别? ConcurrentHashMap是线程安全的,而HashMap是非线程安全的。ConcurrentHashMap内部使用了分离的桶和锁机制来保证线程安全性,并且多个线程可以同时进行读取操作,而HashMap则没有这样的机制。 3. ConcurrentHashMap的实现原理是什么? ConcurrentHashMap内部使用了分离的桶和锁机制来保证线程安全性。每个桶都有一个独立的锁,多个线程可以同时访问不同的桶,从而提高了并发性能。同时,ConcurrentHashMap还使用了一种被称为“分段锁”的机制,即将整个哈希表分为多个段,每个段都有一个独立的锁来保证线程安全。 4. ConcurrentHashMap如何保证线程安全性? ConcurrentHashMap使用了分离的桶和锁机制来保证线程安全性。每个桶都有一个独立的锁,多个线程可以同时访问不同的桶,从而提高了并发性能。同时,ConcurrentHashMap还使用了一种被称为“分段锁”的机制,即将整个哈希表分为多个段,每个段都有一个独立的锁来保证线程安全。 5. ConcurrentHashMap的性能如何? ConcurrentHashMap的性能非常好,尤其是在高并发环境下。由于它使用了分离的桶和锁机制,可以同时进行读取操作,从而大幅度提高了读取性能。同时,它还使用了分段锁机制来保证线程安全性,这也进一步提高了并发性能。 6. ConcurrentHashMap的缺点是什么? ConcurrentHashMap的主要缺点是占用内存较大,因为它需要维护多个分离的桶和锁。此外,由于它使用了分段锁机制,所以在进行写操作时可能会出现锁竞争,导致性能下降。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值