阿杰,我给你整理一份 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
发表回复