Java面试总结

时间:2025-03-08 08:37:44
1.synchronized 通过监视器锁来实现线程同步 2.每个 Java 对象都有一个监视器锁 3.线程在获取了对象的监视器锁后,可以执行被修饰的代码 4.线程在释放了对象的监视器锁后,其他线程可以尝试获取监视器锁 5.Monitor 的结构: 1.Owner:当前持有锁的线程 2.EntryList:等待获取锁的线程队列 3.WaitSet:调用 wait() 方法后进入等待状态的线程队列 6.锁的状态: 1.无锁状态:对象未被任何线程锁定 2.偏向锁:只有一个线程访问锁时,JVM 会优化为偏向锁,避免 CAS 操作 1.轻量级锁:多个线程竞争锁时,JVM 会升级为轻量级锁,使用 CAS 操作 1.重量级锁:当竞争激烈时,JVM 会升级为重量级锁,线程进入阻塞状态 5.对象头与锁:Java 对象在内存中的布局分为三部分: 1.对象头(Header):包含锁信息、GC 信息等 2.实例数据(Instance Data):对象的字段数据 3.对齐填充(Padding):为了内存对齐而填充的字节 6.synchronized 的锁信息存储在对象头中,对象头的主要组成部分包括: 1.Mark Word:存储对象的哈希码、锁状态、GC 分代年龄等信息 1.Klass Pointer:指向对象所属类的元数据 7.Mark Word中锁的状态通过不同的标志位来表示 1.无锁状态:锁标志位为 01 2.偏向锁:锁标志位为 01,并记录偏向线程 ID 3.轻量级锁:锁标志位为 00 4.重量级锁:锁标志位为 10 8.锁的升级过程:JVMsynchronized 的锁进行了优化,锁的状态会根据竞争情况逐步升级 1.偏向锁 1.适用场景:只有一个线程访问锁 2.原理:在对象头中记录偏向线程 ID,后续该线程可以直接获取锁,无需 CAS 操作 3.优点:减少锁竞争的开销 2.轻量级锁 1.适用场景:多个线程交替访问锁,但没有竞争 2.原理:使用 CAS 操作将对象头的 Mark Word 替换为指向线程栈中锁记录的指针 3.优点:避免线程阻塞,减少上下文切换 3.重量级锁 1.适用场景:多个线程竞争锁 2.原理:将对象头的 Mark Word 替换为指向 Monitor 的指针,线程进入阻塞状态 3.优点:解决高并发竞争问题 9.synchronized 的底层实现 1.字节码层面:当方法或代码块被 synchronized 修饰时,JVM 会在字节码中插入 monitorenter 和 monitorexit 指令 1.monitorenter:获取对象的 Monitor 2.monitorexit:释放对象的 Monitor 2.JVM 层面 1.JVM 会根据锁的状态和竞争情况,选择合适的锁机制(偏向锁、轻量级锁、重量级锁)。 2.如果锁竞争激烈,JVM 会将锁升级为重量级锁,线程进入阻塞状态,等待锁释放 10.synchronized 的优化:为了提升 synchronized 的性能,JVM 引入了以下优化技术 1.锁消除(Lock Elimination):JVM 在编译时通过逃逸分析,判断锁对象是否只被一个线程访问。如果是,则消除锁 2.锁粗化(Lock Coarsening):如果多个连续的锁操作作用于同一个对象,JVM 会将多个锁合并为一个锁,减少锁的获取和释放次数 3.自适应自旋(Adaptive Spinning):在轻量级锁竞争时,线程会自旋等待锁释放。JVM 会根据历史数据动态调整自旋次数