wait和notify这个为什么要在synchronized代码块中?
下面从多个维度,全面详细地讲解 Java 中的 lock(以 ReentrantLock 为代表)和 synchronized 的区别,包含原理、性能、用法和适用场景。
一、基本概念
| 方面 | synchronized | Lock(通常指 ReentrantLock) |
|---|---|---|
| 语法 | Java 关键字,内置语言结构 | 接口和实现类,Java.util.concurrent.locks 包 |
| 功能 | 用于同步代码块或方法,保证线程互斥执行 | 提供更灵活的锁机制,支持公平锁、可中断锁等 |
| 出现时间 | Java 1.0 就有 | Java 5 引入 |
二、详细区别
| 比较维度 | synchronized | ReentrantLock |
|---|---|---|
| 锁类型 | 内置锁(监视器锁,Monitor Lock) | 显式锁(基于 AQS 实现的可重入独占锁) |
| 灵活性 | 只能锁整个方法或代码块 | 提供更多方法如 lockInterruptibly()、tryLock() |
| 可中断性 | 不支持中断等待锁(阻塞不可中断) | 支持可中断锁请求,调用线程可被中断 |
| 公平锁支持 | 不支持公平锁 | 支持公平锁和非公平锁(默认非公平) |
| 锁释放方式 | JVM 自动释放锁(代码块结束自动释放) | 需手动调用 unlock() 释放,容易忘记导致死锁 |
| 性能 | JDK 1.6+ 引入偏向锁、轻量级锁优化,性能提升显著 | 性能稳定,复杂场景下有优势 |
| 死锁检测 | JVM 不提供显式死锁检测 | 可用 API 查询是否被持有,可实现死锁检测 |
| 条件变量支持 | 通过 wait()/notify()/notifyAll() 实现线程通信 | 通过 Condition 对象实现多条件等待/通知 |
| 重入性 | 都是可重入锁 | 都是可重入锁 |
| 异常处理 | 锁释放自动,异常抛出不会影响锁释放 | 必须在 finally 中释放锁,否则可能死锁 |
三、使用示例对比
1. synchronized
public synchronized void syncMethod() {
// 代码块被锁保护
}
或
public void syncBlock() {
synchronized (this) {
// 代码块被锁保护
}
}
锁释放自动发生,无需显式代码。
2. ReentrantLock
private final ReentrantLock lock = new ReentrantLock();
public void lockMethod() {
lock.lock();
try {
// 代码块被锁保护
} finally {
lock.unlock(); // 必须释放锁
}
}
四、性能比较
- 早期(JDK 1.5 之前)
synchronized性能较差,ReentrantLock优势明显 - JDK 1.6+ 引入偏向锁、轻量级锁,
synchronized性能大幅提升 - 在无锁竞争或低竞争环境,
synchronized更轻量 - 在高竞争、多线程等待场景,
ReentrantLock通过灵活调度可更高效
五、功能区别细节
| 特性 | synchronized | ReentrantLock |
|---|---|---|
| 公平锁 | 无 | 支持,通过构造函数设置 |
| 可中断锁 | 不支持 | 支持 lockInterruptibly() |
| 尝试获取锁 | 无 | 支持 tryLock() |
| 多条件等待 | 一个条件(wait/notify) | 多个条件支持 Condition |
| 锁释放安全 | JVM自动释放 | 程序员必须手动释放 |
| 代码简洁性 | 简单,写法少 | 代码多,需写 try-finally |
六、适用场景建议
| 场景类型 | 推荐使用 |
|---|---|
| 简单同步 | synchronized |
| 需要公平锁 | ReentrantLock(构造参数true) |
| 需要可中断锁 | ReentrantLock |
| 需要尝试非阻塞锁 | ReentrantLock.tryLock() |
| 需要多个条件变量 | ReentrantLock + Condition |
| 代码简洁优先 | synchronized |
七、总结表格
| 特性 | synchronized | ReentrantLock |
|---|---|---|
| 出现时间 | Java 1.0 | Java 5 |
| 锁类型 | JVM 内置锁 | 显式锁 |
| 可重入 | 是 | 是 |
| 可中断 | 否 | 是 |
| 公平锁 | 否 | 支持 |
| 锁释放 | 自动 | 手动 |
| 条件变量 | wait/notify | Condition |
| 代码简洁 | 简单 | 复杂 |
| 性能 | JDK 1.6+ 低竞争时更优 | 高竞争时更优 |
八、官方参考链接
更多详细内容请关注其他相关文章!