阿杰,我给你整理一份 Lock 与 synchronized 的区别详解,包含概念、用法、特点对比和适用场景。
一、概念
| 特性 | synchronized | Lock(java.util.concurrent.locks.Lock) |
|---|
| 类型 | 内置锁(JVM 层面) | 显示锁(Java 类库提供) |
| 用法 | 通过关键字修饰方法或代码块 | 创建 Lock 对象,调用 lock() / unlock() |
| 机制 | JVM 自动加锁、解锁 | 手动加锁、解锁,需显式调用 unlock() |
二、基本用法
1. synchronized
修饰方法
public synchronized void add() {
// 临界区
count++;
}
修饰代码块
public void add() {
synchronized(this) {
count++;
}
}
2. Lock
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
Lock lock = new ReentrantLock();
public void add() {
lock.lock(); // 上锁
try {
count++;
} finally {
lock.unlock(); // 解锁
}
}
注意:Lock 必须在 finally 块中释放锁,否则可能发生死锁。
三、主要区别
| 维度 | synchronized | Lock |
|---|
| 是否可中断 | 不可中断 | 可中断(lockInterruptibly) |
| 超时获取锁 | 不支持 | 支持 tryLock(long time, TimeUnit unit) |
| 公平性 | 不支持 | 支持公平锁(ReentrantLock(boolean fair)) |
| 释放锁 | JVM 自动释放 | 必须手动释放 unlock() |
| 性能 | Java 1.6+ 已优化,可适应轻量级锁 | 高并发场景下性能优于 synchronized |
| 条件变量 | wait()/notify()/notifyAll() | 支持多个 Condition,灵活等待/通知 |
| 适用场景 | 简单同步 | 复杂同步、可中断、超时等待、多个条件队列 |
四、适用场景对比
| 场景 | 推荐使用 |
|---|
| 简单同步方法或代码块 | synchronized |
| 高并发场景 | ReentrantLock |
| 需要公平锁 | Lock |
| 需要超时获取锁 | Lock(tryLock) |
| 需要中断等待 | Lock(lockInterruptibly) |
| 多条件等待 | Lock + Condition |
五、注意事项
- synchronized:不用手动释放锁,JVM 自动处理;容易避免死锁,但灵活性差。
- Lock:必须在 finally 中释放锁,否则可能死锁;适合复杂业务场景。
- 性能:
- Java 1.6+,synchronized 已优化为轻量级锁和偏向锁
- Lock 在高并发、频繁加锁/解锁场景性能略优
六、总结
- synchronized:简单、安全,适合方法或代码块的同步。
- Lock:灵活、高级,用于复杂业务场景,需要手动释放锁、支持中断、超时和多条件。
- 选择原则:
- 业务简单 → synchronized
- 高并发或复杂同步 → Lock
发表回复