ConcurrentHashMap 常见面试题详解

ConcurrentHashMap

1. ConcurrentHashMap的数据结构

数组 + 链表, 采用了分段锁的实现机制

2. ConcurrentHashMap初始化

首先会创建segment数组,长度为默认(16)或传入的并发值的大于等于的2的次方数,不可扩容
初始化(s0)segment对象并保存,并初始化他的属性,创建一个entry数组,entry数组初始化长度为 (容器长度 / segment数组长度)
    大于等于2的次方,在下一次进行添加数据的时候,会直接取这个s0对象
这里初始化了他的segment[0]

3. ConcurrentHashMap如何存取数据的

1.7:
    put():
        1.先计算出key值的hash值,然后通过hash值(对segment[]进行取余)找到数组中对应的segment对象
        2.尝试获取锁,失败则自旋保证成功。
        3.获取锁,然后通过计算出的hash值(对hashentry[]进行取余)找出对应的entry对象
        	遍历链表中,查找有没有相同key值对象
            有: 旧值覆盖新值
            没有: 添加到链表中(1.7/头部  |  1.8/尾部)
    get():
        1.通过key值的hash值定位到对应segment对象,再通过hash值定位到具体的entry对象
        2.遍历链表,通过equals取出数据
        3.由于 HashEntry 中的 value 属性是用 volatile 关键词修饰的
        	保证了内存可见性,所以每次获取时都是最新值
        4.整个过程不需要加锁

1.8:
	put():
		1.根据 key 计算出 hashcode
		2.判断是否需要进行初始化。
		3.即为当前 key 定位出的 Node,如果为空表示当前位置可以写入数据
		4.利用 CAS 尝试写入,失败则自旋保证成功。如果都不满足,则利用 synchronized 锁写入数据
		5.如果数量大于 树形化阈值 则要转换为红黑树。
	get():
		1.根据计算出来的 hashcode 寻找segment,如果就在桶上那么直接返回值。
		2.如果是红黑树那就按照树的方式获取值。
		3.就不满足那就按照链表的方式遍历获取值。
	

4. 1.7、1.8 实现有何不同?为什么这么做?

线程同上.

数据结构:
	1.7: 数组 + 链表
	1.8: 
		1.7的底层还是链表,在查询数据的时候需要遍历,导致效率很低
		1.8和HashMap比较像,也引入了红黑树,把值和next采用了volatile去修饰,保证了可见性

5. volatile的特性是啥?

volatile是Java提供的一种轻量级的同步机制:
	1.保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值
		这新值对其他线程来说是立即可见的。(实现可见性)
	2.禁止进行指令重排序。(实现有序性)
	3.volatile 只能保证对单次读/写的原子性。i++ 这种操作不能保证原子性。

6. ConcurrentHashMap 线程安全怎么做的?

1.7:
	采用了分段锁的机制,当一个线程占用锁时,不会影响到其他的Segment对象
1.8:
	抛弃了原来的分段锁,采用了 CAS 和 synchronized 来保证并发的安全

7. 不安全会导致的问题


8. CAS是啥?ABA是啥?场景有哪些,怎么解决?

CAS:
	是乐观锁的一种实现方式,是一种轻量级锁
	线程在读取数据时不进行加锁,在准备写回数据时,比较原值是否修改,
	若未被其他线程修改则写回,若已被修改,则重新执行读取流程
ABA:
	当线程对值的修改过程中,另一个线程也对这个值进行了修改,并把它改为了原来的值
		此时,这个值已经不是和原的值了
    解决方案:
    	版本号 / 时间戳

9. synchronized锁升级策略

	1.先使用 偏向锁 优先同一线程然后再次获取锁
	2.如果失败,就升级为 CAS 轻量级锁,失败就会短暂自旋,防止线程被系统挂起。
	3.最后如果以上都失败就升级为重量级锁。
  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一些可能被问到的concurrentHashmap面试: 1. 什么是ConcurrentHashMapConcurrentHashMap是Java中的一个线程安全的哈希表。它是由多个分离的桶组成的,每个桶都可以被独立地锁住,从而使得多个线程可以同时访问不同的桶,从而提高了并发性能。 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、付费专栏及课程。

余额充值