1.ReentrantLock的实现原理

  ReentrantLock是一个可重入的互斥锁,具有尝试非阻塞地获取锁、可中断的锁获取、支持公平性等特点。ReentrantLock通过内部类Sync实现核心功能,Sync继承了AQS类(构建锁和其他同步组件的框架)。AQS通过int型的成员变量表示同步状态,通过内置的FIFO来管理线程的排队等待。

可重入性

  当一个线程获取了 ReentrantLock 后,它可以再次获取该锁而不会造成死锁,这是因为 ReentrantLock记录当前拥有锁的线程以及该线程获取锁的次数。只有当该线程释放锁的次数与它获取锁的次数相同时,锁才会被真正释放

锁获取

  • lock():调用此方法会使当前线程尝试获取锁。如果锁不可用,当前线程会被阻塞,直到锁可用。
  • tryLock():尝试非阻塞地获取锁。如果锁可用,当前线程获取锁并立即返回 true;否则返回 false,不会等待。
  • tryLock(long timeout, TimeUnit unit):尝试在指定的时间内获取锁。如果在给定时间内锁可用,当前线程获取锁并返回 true;如果超时或锁不可用,返回 false。

2.垃圾回收算法

  垃圾回收器用于自动管理Java内存。垃圾回收器算法有Serial GC、Parallel GC/Parallel Old GC、CMS以及G1等算法

 Serial GC:Serial GC是单线程的垃圾回收器垃圾回收时会暂停所有用户线程(STW)、包括新生代的Minor GC和老年代的Major GC,采用标记清除或标记压缩算法

Parallel GC:Parallel GC是Serial GC的并行版本,在多核环境下使用多个线程进行垃圾回收,回收过程中暂停所有用户线程。多核环境行性能较好,显著缩短STW时间;并发场景下,并行处理可能导致系统负载较大;采用复制算法进行垃圾回收

CMS:初始标记、并发标记、重新标记、并发清除大部分工作并发执行,减少STW,适用于响应高场景。采用标记-清除算法,碎片化严重,需定期进行并发压缩

G1:区域化管理(分代,即新生代和老年代)、并发标记、空间回收、完整GC采用标记-整理算法进行实时垃圾回收大量小对象回收不如其他收集器

3.Redis的分布式锁实现

   Redis的分布式锁实现依赖于其原子性和高性能。

3.1.使用SETNX命令

SERNX(SET if Not eXists)命令用于在键不存在时设置键值。该命令可用于简单实现分布式锁:

  • 加锁:SETNX lockKey;
  1. 如果lockKey不存在,SETNX会设置键并返回1表示成功获取锁
  2. 如果lockKey存在,SETNX不会设置键并返回9表示获取锁失败
  • 解锁:使用DEL lockKeyy命令删除锁

3.2 使用SET命令带过期时间

SET命令可以结合EX或PX选项设置键的过期时间,避免锁无限期持有

  • 加锁:SET lockKey value EX 30SET lockKey value PX 30000
  • EX后跟秒数,PX后跟毫秒数,表示锁的过期时间。
  • NX选项确保只在键不存在时设置值。
  • 解锁:同样使用DEL lockKey命令。

3.3 使用Lua脚本与Redis的call方法结合

3.4 RedLock算法

  RedLock是一种更安全的分布式锁实现,它通过在多个Redis实例上尝试获取锁提高锁的可靠性。

  1. 客户端获取当前时间戳。
  2. 依次尝试在多个Redis实例上加锁,每个实例都需要设定相同的过期时间和随机字符串(nonce)。
  3. 客户端计算加锁操作的总时间,并将其与指定的超时时间进行比较。如果总时间小于超时时间,并且超过一半的Redis实例加锁成功,则认为加锁成功。否则,客户端需要在所有实例上尝试解锁操作。

3.5 注意事项:

  • 安全性:确保解锁操作只能由加锁的客户端执行,避免误删其他客户端的锁。
  • 死锁预防设置锁的过期时间以避免死锁
  • 重试机制:在获取锁失败时,可能需要重试。
  • 锁的公平性:确保所有客户端都有公平的机会获取锁。

4.强引用、软引用、弱引用、虚引用

  在Java中,对象引用分为强、软、弱、虚等四种引用。四种对象引用的强度依次减弱,对GC也有不同的影响。

强引用:

  强引用是Java中最常见的引用类型。当对象被强引用关联时,它将一直被保留在内存中,直到强引用被显式地断开(例如,将其设置为null。只要强引用存在,垃圾收集器就不会回收这个对象

Object obj = new Object()

软引用:软引用关联的对象在内存不足时才会被垃圾收集器回收。软引用通常用于实现内存敏感的缓存,可以通过java.lang.ref.SoftReference类创建

SoftReference<Object>softRef = new SoftReference<>(new Object)

弱引用:只要垃圾收集器运行,弱引用关联的对象就可能被回收不管当前内存是否充足。弱引用通常用于实现缓存等需要快速响应内存变化的场景。(ThreadLocal)

WeakReference<Object>weakRef = new WeakRefernce<>(new Object);

虚引用:虚引用几乎不阻止垃圾收集器回收关联的对象。虚引用主要用于跟踪对象被回收的状态,当对象即将被回收时,可以将虚引用加入到一个引用队列中,从而可以执行一些清理工作

5.Spring好处

  1. 模块化:根据需要导入合适模块
  2. IOC容器:容器统一管理对象生命周期和依赖关系,降低耦合,提高代码维护性和灵活性
  3. AOP:在不改变源代码的情况下,增加业务功能,提高代码维护性
  4. 事务管理:保护数据完整性和一致性
  5. 集成性强:Mybatis、Hibernate

6.循环依赖如何解决

循环依赖是指两个类相互依赖各自类的实例。Spring通过三级缓存解决循环依赖,循环依赖中依赖注入的方式有构造函数注入,无法解决,但可以解决setter注入形式的循环依赖。Spring的对象分为三种,分别是早期对象存储在一级缓存的SingletonObjects中,正在创建的对象存储在二级缓存的earlySingletonObjects中,通过ObjectFactory创建的对象存储在三级缓存中,当出现循环依赖时通过三级缓存创建一个所依赖的对象即可解决循环依赖问题。

7.Mysql的悲观锁和乐观锁

乐观锁:假设数据在更新时不会发生冲突,因此在读取数据时不加锁,只会在更新数据时检查是否有其他事务对数据进行修改;

悲观锁:假设数据在更新时会发生冲突,因此读取数据时加锁,阻止其他事务对数据的修改