synchronized 和 ReentrantLock 的区别?
抓住一句总纲就行:
synchronized是 Java 内置的关键字锁,ReentrantLock是 JDK 提供的显式锁。它们都能实现互斥和可重入,但ReentrantLock更灵活、功能更多。
一、先说共同点
它们两个都能做到:
-
互斥:同一时刻只允许一个线程进入临界区
-
可重入:同一个线程拿到锁后,可以再次进入被同一把锁保护的代码
所以本质上,它们都是为了解决线程安全问题。
二、核心区别
你面试时主要说这 5 点就够了。
1. 使用方式不同
synchronized 是关键字,写法简单:
synchronized(obj) {
// 临界区
}
ReentrantLock 是对象,需要手动加锁、手动释放锁:
lock.lock();
try {
// 临界区
} finally {
lock.unlock();
}
所以:
synchronized用起来更简单,ReentrantLock更灵活,但必须手动释放锁。
2. 锁获取方式不同
synchronized 获取锁失败后,只能一直阻塞等待。
ReentrantLock 更灵活,支持:
-
tryLock():尝试获取锁,拿不到直接返回 -
tryLock(time):等待一段时间拿锁 -
lockInterruptibly():可中断获取锁
所以:
ReentrantLock可以尝试拿锁、定时拿锁、可中断拿锁,而synchronized不行。
3. 是否支持公平锁
synchronized 是非公平锁,不能自己指定公平策略。
ReentrantLock 可以创建:
-
公平锁
-
非公平锁
比如:
new ReentrantLock(true)
表示公平锁,先来先得。
所以:
ReentrantLock支持公平锁,synchronized不支持。
4. 是否支持多个条件队列
synchronized 搭配的是:
-
wait() -
notify() -
notifyAll()
只有一个隐式条件队列。
ReentrantLock 可以配合 Condition 创建多个等待队列:
Condition notFull = lock.newCondition();
Condition notEmpty = lock.newCondition();
这在生产者消费者模型里更灵活。
所以:
ReentrantLock支持多个 Condition,线程唤醒更精细。
5. 性能和实现层面
早期 JDK 版本里,ReentrantLock 性能优势更明显。
但从 JDK 1.6 以后,synchronized 做了很多优化,比如:
-
偏向锁
-
轻量级锁
-
锁粗化
-
锁消除
所以现在一般不能简单说谁性能一定更好。
更准确的说法是:
现在两者性能差距没有以前那么大,更多是功能和使用场景的区别。
三、什么时候用哪个
用 synchronized
适合:
-
代码简单
-
锁逻辑不复杂
-
只需要基本互斥
-
更看重易用性
优点是语法简单,不容易忘记释放锁。
用 ReentrantLock
适合:
-
需要尝试加锁
-
需要可中断锁
-
需要公平锁
-
需要多个条件队列
-
锁控制更复杂的场景
四、面试回答版
synchronized和ReentrantLock都可以实现线程同步,并且都支持可重入。它们的主要区别在于:
synchronized是 Java 内置关键字,使用简单,JVM 自动加锁和释放锁;ReentrantLock是 JDK 提供的显式锁,需要手动lock和unlock,但功能更灵活。比如
ReentrantLock支持tryLock、可中断获取锁、公平锁,以及通过Condition实现多个条件队列,而synchronized不支持这些高级特性。性能上从 JDK 1.6 之后synchronized已经做了很多优化,所以现在两者性能差距不一定明显,更多还是根据业务场景选择:简单同步用synchronized,复杂并发控制用ReentrantLock。
更多推荐




所有评论(0)