目录
ReentrantLock(可重入锁)和synchronized是Java中实现线程同步的两种核心机制,
一、核心功能与特性
| 对比维度 | synchronized | ReentrantLock |
| 实现方式 | 关键字,由JVM底层实现(C++代码) | 类( |
| 可重入性 | 支持(同一线程可多次获取同一把锁,自动记录重入次数) | 支持(通过 |
| 锁释放 | 自动释放(同步块/方法执行完毕或异常时) | 手动释放(必须在 |
| 锁类型 | 非公平锁(默认),无法切换为公平锁 | 可通过构造函数指定公平/非公平锁( |
| 中断响应 | 不支持(线程获取锁时,无法被中断,会一直阻塞) | 支持(通过 |
| 超时获取 | 不支持(获取不到锁会一直阻塞) | 支持( |
| 条件变量 | 不支持(仅能通过对象的 | 支持(通过 |
| 锁状态查询 | 无法直接查询 | 可查询( |
| 锁实现机制 |
|
|
二、性能对比
- JDK 6之前:
synchronized性能较差(存在重量级锁的优化不足),ReentrantLock性能更优。 - JDK 6及之后:JVM对
synchronized进行了大量优化(如偏向锁、轻量级锁、锁消除、锁粗化等),两者性能差异不大,在多数场景下synchronized甚至更优(JVM对其优化更深入)。
三、使用方式
| 场景 | 推荐选择 | 原因 |
| 简单的同步代码块/方法 |
| 语法简洁,无需手动释放锁,不易出错,JVM优化充分。 |
| 需要公平锁机制 |
| 可通过构造函数指定公平锁,保证线程获取锁的顺序(按等待时间排序)。 |
| 需要中断等待锁的线程 |
|
|
| 需要超时获取锁 |
|
|
| 需要多条件等待/唤醒 |
|
|
| 需要查询锁状态 |
| 提供多种方法查询锁状态,便于调试和监控。 |
| 资源竞争激烈的高并发场景 | 两者均可(视情况) | JDK 6+后性能接近, |
四、典型代码示例
1. synchronized的使用
// 同步方法
public synchronized void syncMethod() {
// 同步逻辑
}
// 同步代码块
public void syncBlock() {
synchronized (this) {
// 同步逻辑
}
}
2. ReentrantLock的使用
import java.util.concurrent.locks.ReentrantLock;
public class LockExample {
private final ReentrantLock lock = new ReentrantLock(); // 非公平锁(默认)
// private final ReentrantLock lock = new ReentrantLock(true); // 公平锁
public void lockMethod() {
lock.lock(); // 获取锁
try {
// 同步逻辑
} finally {
lock.unlock(); // 必须在finally中释放锁
}
}
// 超时获取锁
public boolean tryLockWithTimeout() throws InterruptedException {
if (lock.tryLock(1, TimeUnit.SECONDS)) { // 1秒超时
try {
// 同步逻辑
return true;
} finally {
lock.unlock();
}
}
return false;
}
}
五、总结
synchronized的优势:语法简单、自动释放锁、不易出错、JVM优化成熟,适合大多数基础同步场景。ReentrantLock的优势:功能更灵活(公平锁、中断、超时、多条件),适合复杂同步场景,需手动管理锁释放(注意finally块)。
2068

被折叠的 条评论
为什么被折叠?



