[面试题] synchronized和reentrantLock的区别是什么?
📖 知识讲解版 (温故知新)
- 实现层次:
synchronized是 JVM 层面的关键字(底层通过 monitor 对象实现);ReentrantLock是 JDK 层面(API层面)基于 AQS 实现的类。 - 锁的释放:
synchronized会自动释放锁(发生异常也会释放);ReentrantLock必须在 finally 块中手动unlock()。 - 灵活性:
ReentrantLock更灵活,支持公平锁/非公平锁、支持响应中断 (lockInterruptibly)、支持超时尝试获取锁 (tryLock)。synchronized只能是非公平锁且不可中断。 - 性能:JDK 1.6 引入锁升级(偏向锁->轻量级锁->重量级锁)后,两者在一般并发下性能相近;极端高并发竞争下,
ReentrantLock的性能更稳定。
🎤 面试实战版 (高手逐字稿)
Q:synchronized和reentrantLock的区别是什么?
💬 高手逐字稿:
关于 synchronized 和 ReentrantLock 的区别,我认为可以从三个核心维度来对比:底层实现、使用灵活性以及性能。
第一,从底层实现来看。synchronized 是 Java 语言内置的关键字,它是依赖于 JVM 层面的 Monitor 对象来实现的,无论是加锁还是解锁都由虚拟机自动控制。而 ReentrantLock 是 JDK 并发包里提供的一个类,它是基于我们在 Java 层面实现的 AQS(同步器)框架来完成的。
第二,从使用灵活性来看,ReentrantLock 明显更胜一筹。synchronized 加锁后,如果拿不到锁就会死等,而且无法中断。但 ReentrantLock 提供了丰富的 API,比如 tryLock() 可以尝试获取锁,拿不到可以直接返回不阻塞;比如 lockInterruptibly() 可以在等待锁的过程中响应中断;而且它还支持在构造时选择是公平锁还是非公平锁,而 synchronized 只能是非公平锁。另外,ReentrantLock 必须手动在 finally 块中释放锁,否则容易死锁。
第三,从性能来看。在早期版本,ReentrantLock 性能远高于 synchronized。但在 JDK 1.6 之后,官方对 synchronized 进行了大刀阔斧的“锁升级”优化(引入了偏向锁、轻量级锁)。现在的日常场景中,两者的性能其实差不多了。
这时候其实我们需要有技术选型的考量:绝大多数普通场景下,我更推荐直接用 synchronized,因为代码简洁,且 JVM 会自动帮我们清理。只有当需要用到高级特性(比如需要公平锁、需要超时中断、或者读多写少需要用对应的 ReentrantReadWriteLock 时),我才会考虑上 ReentrantLock。不知道贵司的代码规范里,对这两种锁的使用场景有强制规定吗?