20230913java面经整理

1.hashmap为什么重写hashcode必须重写equals?不重写hashcode?

hashcode判断对象存放的索引值,equals判断相同索引下对象是否相同,不同则存放(链表)
hashcode提升查询效率,通过哈希计算,equals相等hashcode一定 相等
因为业务判断equals不一定严格对象相等,所以要重写equals
规定:equals的对象必须有相同的hashcode
不重写的话导致hashmap不可以正常运作

2.concurrenthashmap数据结构,怎么实现线程安全?

hashmap在多线程put的时候,hash碰撞时通过链表方式存,没有同步的话可能会覆盖造成数据丢失
在这里插入图片描述
volatile:改动val和next对于其他线程都可见
cas:put的时候,根据key的hashcode定位,定位完之后时null需要使用cas进行插入,compareAndSwap
synchronized:头节点不是null,synchronized加锁头节点
在这里插入图片描述

3.reentranlock介绍一下,怎么实现

基于AQS实现:同步队列和条件队列的抽象类
同步双向链表,条件单项链表,存的等待状态的线程,aqs管理线程之间的等待状态-唤醒的工作
同步队列有独占模式和共享模式,区别在于是不是传递唤醒
定义锁:继承aqs后重写获取锁、释放锁以及管理state
reentranlock:通过重写tryAcquire和tryRelease实现lock和unlock
在这里插入图片描述
独占锁、悲观锁,默认非公平锁
lock通过cas设置state
公平锁按照同步队列中的先到先得的顺序,后来的不能抢先获得锁;非公平的如果看到state是0直接抢占
tryRelease看是否有重入,知道释放完state=0再唤醒后继节点
tryLock在规定时间内进行循环获取锁
等待-通知机制:synchronized + object或wait+notify(notifyAll)
ReentranLock + Condition使用条件队列实现wait、notify、notifyall语义
await将同步队列转移条件队列,signal将条件队列转移同步队列,只有同步队列才可以获得锁
reentrantlock是aqs实现,synchronized是jvm实现通过monitor对象/对象头实现
在这里插入图片描述

4.synchronize怎么实现

jvm通过进入和退出monitor对象实现代码块同步,使用monitorenter和monitorexit指令实现,方法同步通过access flags后边的synchronized标识,如果有标识则持有monitor
锁优化:无锁-》偏向锁-〉轻量级锁-》重量级锁
偏向锁:只有一个线程执行
轻量级锁:多个线程交替执行未发生竞争,将对象的mark word复制到当前线程的lock record中
在这里插入图片描述

5.cas介绍一下

CAS 全称是 compare and swap,是一种用于在多线程环境下实现同步功能的机制。CAS 操作包含三个操作数 – 内存位置、预期数值和新值。CAS 的实现逻辑是将内存位置处的数值与预期数值想比较,若相等,则将内存位置处的值替换为新值。若不相等,则不做任何操作。

aba问题:对每一次cas设置版本号,atomicStampedReference可以解决aba问题
循环时间开销大:如果jvm可以支持pause可提高效率,可延迟操作
只可保证一个共享变量的原子

6.volatile原理,使用场景

使用volatile来解决共享变量可见性
1.当一个线程写一个volatile变量时,JMM会把该线程对应的本地内存中的变量值强制刷新到主内存中去;
2.这个写会操作会导致其他线程中的这个共享变量的缓存失效,要使用这个变量的话必须重新去主内存中取值。3.禁止指令重排序优化,因为在多线程不一定会正确
4.为了实现volatile的内存语义,编译器在生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。同时内存屏障还能保证内存的可见性
使用场景:
1.用于状态标志,指示一个重要的一次性时间
2.一次性发布,可能遇到某个对象的更新值和该对象状态的旧值同时存在,例如双重检测单例,不用volatile的话jvm进行指令重排会返回未初始化的对象
在这里插入图片描述

7.事务隔离级别

脏读:脏读指的是读到了其他事务未提交的数据,未提交意味着这些数据可能会回滚
可重复读:在一个事务内,最开始读到的数据和事务结束前的任意时刻读到的同一批数据都是一致的
不可重复读:在同一事务内,不同的时刻读到的同一批数据可能是不一样的,可能会受到其他事务的影响
幻读:针对数据插入(INSERT)操作来说的


读未提交,顾名思义,就是一个事务可以读取另一个未提交事务的数据。
读提交,顾名思义,就是一个事务要等另一个事务提交后才能读取数据。
可重复读,就是在开始读取数据(事务开启)时,不再允许修改操作
串行化,后一个事务的执行必须等待前一个事务结束


使用mvvc多版本并发控制实现可重复读,生成快照
可重复读是在事务开始的时候生成一个当前事务全局性的快照,而读提交则是每次执行语句的时候都重新生成一次快照。

8.可重复读如何阻止幻读

解决幻读用的也是锁,叫做间隙锁,MySQL 把行锁和间隙锁合并在一起,解决了并发写和幻读的问题,这个锁叫做 Next-Key锁。
next-key lock = 行锁 + 间隙锁
间隙锁是多个行组成的区间,行锁是一行
有索引的话,未插入的行以及记录两边的区间加入间隙锁
没有索引的话,为整个表加入间隙锁

9.bean的生命周期

实例化 Instantiation
属性赋值 Populate
初始化 Initialization
销毁 Destruction
在这里插入图片描述

在这里插入图片描述

10.bean如何注入值

构造函数注入、set方法注入
xml配置文件注入,注解方式@value注入
xml配置中的constructor-arg可以根据name或者index注入
xml配置中的set注入直接根据name注入
p命名空间简化set注入,普通属性or引用
c明明空间简化构造器注入,普通属性or引用

猜你喜欢

转载自blog.csdn.net/weixin_40986490/article/details/132847112