谈谈你对ConcurrentHashMap的理解

Java面试 潘老师 8个月前 (09-04) 167 ℃ (0) 扫码查看

Java面试题:谈谈你对ConcurrentHashMap的理解

得分点:

数组+链表+红黑树、锁的粒度

标准回答:

在JDK8中,ConcurrentHashMap的底层数据结构与HashMap类似,也采用了“数组+链表+红黑树”的结构。但它通过锁的粒度来实现线程安全,降低了锁的竞争范围,提高了并发性能。

1. 初始化数组或头节点时不加锁: 在初始化数组或头节点时,ConcurrentHashMap并没有加锁,而是采用CAS(Compare and Swap)的方式进行原子替换操作。这使得初始化操作可以在多个线程之间并发执行,不会阻塞其他操作。

2. 锁的粒度是槽: 当插入数据时,ConcurrentHashMap会进行加锁处理,但锁定的不是整个数组,而是某个槽中的头节点。这意味着锁的粒度是槽,而不是整个数组,因此多个线程可以同时操作不同的槽,从而提高了并发性能。

3. 扩容时的并发处理: 扩容时,ConcurrentHashMap仍然会进行加锁处理,但锁定的仍然是槽中的头节点。多个线程可以同时参与数组的扩容工作,每个线程负责一段连续槽位的数据迁移任务。线程首先要通过CAS操作来争夺一段槽位的迁移权,获得任务后会锁定槽中的头节点,然后将链表或树中的数据迁移到新的数组中。

4. 查找数据时不加锁: 在查找数据时,ConcurrentHashMap并不会加锁,因此查找操作的性能很好。在扩容过程中,仍然可以进行查找操作。如果某个槽位还未进行数据迁移,查找线程可以直接从旧数组中找到数据。如果某个槽位已经迁移完成,但整个扩容过程还未结束,扩容线程会创建一个转发节点存放在旧数组中,查找线程根据转发节点的提示,从新数组中找到目标数据。

多线程并发扩容的情况下,ConcurrentHashMap会合理分配迁移任务,考虑到硬件处理能力,平均分配任务量。同时,如果计算出的任务数量小于16,它会强制将任务数量设置为16,这是为了充分利用现代CPU的计算能力,避免任务过少浪费CPU资源。


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/javainterview/8660.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】