外观
一句话答案
ReentrantLock 支持公平锁/可中断等待/超时获取/多条件变量,synchronized 是关键字自动释放更简洁。
核心要点
| 维度 | synchronized | ReentrantLock |
|---|---|---|
| 实现层面 | JVM 内置关键字,C++ 实现 | Java 代码实现(AQS) |
| 锁获取 | 自动(进入同步块时) | 手动(lock()) |
| 锁释放 | 自动(退出同步块/异常时,由 JVM 保证) | 手动(unlock(),必须写在 finally 中) |
| 是否可中断 | 不可中断(lock() 会无限等待) | 可中断(lockInterruptibly()) |
| 是否可超时 | 不支持 | 支持(tryLock(timeout, unit)) |
| 是否公平 | 非公平(不保证等待顺序) | 可选(new ReentrantLock(true) 为公平锁) |
| 条件变量 | 只有一个隐式的(wait/notify) | 多个(newCondition(),精确唤醒) |
| 性能 | JDK 6 后优化,差距已不大 | 差距不大,高竞争场景略优 |
| 锁升级 | 支持(偏向→轻量→重量) | 不支持(直接 CAS + AQS) |
正确使用 ReentrantLock 模板:
java
ReentrantLock lock = new ReentrantLock();
lock.lock(); // 获锁
try {
// 业务逻辑
} finally {
lock.unlock(); // 必须在 finally 中释放,防止异常导致永久持锁
}选择建议:
- 大多数场景用
synchronized(更简洁,JVM 自动管理,不会忘记释放) - 需要以下特性时用
ReentrantLock:超时获取锁、可中断等待、公平锁、多个条件变量
追问与易错
追问方向:
- 什么时候必须用 Lock?
- 公平锁为什么性能差?
- 怎么实现可重入的?
易错点:
- ❌ ReentrantLock 一定比 synchronized 好——简单场景 synchronized 更安全
- ❌ 忘记在 finally 中 unlock
💡 记忆锚点
synchronized 是自动门——进去自动锁、出来自动开,简单省心但功能少。ReentrantLock 是手动门禁——可以设超时(tryLock)、可以被叫停(lockInterruptibly)、可以排队取号(公平锁)、可以分多个等候区(多 Condition)。简单场景用自动门,复杂需求上门禁。