Java并发编程:synchronized与Lock的深度对比
前言
synchronized和Lock是Java并发编程中两种最常用的锁机制。面试必问,实战必用。本文深度对比两者的区别,帮你彻底搞懂何时用哪个。
一、基本用法对比
synchronized用法
// 同步方法
public synchronized void method1() {
// 业务代码
}
// 同步代码块
public void method2() {
synchronized(this) {
// 业务代码
}
}
// 静态方法锁Class对象
public static synchronized void method3() {
// 业务代码
}
Lock用法
private final Lock lock = new ReentrantLock();
public void method() {
lock.lock();
try {
// 业务代码
} finally {
lock.unlock(); // 必须手动释放
}
}
二、核心区别对比
| 特性 | synchronized | Lock |
|---|---|---|
| 获取/释放 | 自动 | 手动 |
| 响应中断 | 不支持 | 支持 |
| 超时获取 | 不支持 | 支持 |
| 公平锁 | 非公平 | 可选 |
| 条件变量 | 单条件 | 多条件 |
| 锁状态 | 不可知 | 可查询 |
三、Lock的高级特性
1. 可中断获取
try {
lock.lockInterruptibly();
} catch (InterruptedException e) {
// 响应中断
}
2. 超时获取
if (lock.tryLock(3, TimeUnit.SECONDS)) {
try {
// 获取锁成功
} finally {
lock.unlock();
}
} else {
// 获取锁失败
}
3. 公平锁
// 公平锁:按等待顺序获取
Lock fairLock = new ReentrantLock(true);
// 非公平锁:可能插队
Lock unfairLock = new ReentrantLock(false);
4. 多条件变量
private final Lock lock = new ReentrantLock();
private final Condition notFull = lock.newCondition();
private final Condition notEmpty = lock.newCondition();
// 生产者
public void put(Object item) throws InterruptedException {
lock.lock();
try {
while (isFull()) notFull.await();
// 添加元素
notEmpty.signal();
} finally {
lock.unlock();
}
}
// 消费者
public Object take() throws InterruptedException {
lock.lock();
try {
while (isEmpty()) notEmpty.await();
// 取出元素
notFull.signal();
return item;
} finally {
lock.unlock();
}
}
四、性能对比
JDK 6之后,synchronized做了大量优化(偏向锁、轻量级锁、重量级锁),性能与Lock差距不大。
- 低竞争:synchronized性能更好
- 高竞争:Lock性能略优
五、使用建议
优先使用synchronized:
- 简单的同步场景
- 不需要高级特性
- 代码简洁优先
使用Lock:
- 需要可中断获取锁
- 需要超时获取锁
- 需要公平锁
- 需要多条件变量
六、常见问题
Q: 为什么Lock要手动释放?
A: 因为Lock不会自动释放,如果忘记unlock会导致死锁。这也是Lock的缺点之一。
Q: synchronized是可重入锁吗?
A: 是的,同一个线程可以多次获取同一把synchronized锁。
总结
synchronized简单易用,Lock功能强大。实际开发中,优先使用synchronized,需要高级特性时再考虑Lock。
本文由AI辅助创作。
---
📌 **如果觉得文章对你有帮助,欢迎点赞👍收藏⭐!**
💬 有问题或建议?欢迎在评论区留言讨论~
🔗 更多技术干货请关注作者:弥烟袅绕
📚 本文地址:https://www.cnblogs.com/czlws/p/19788441

浙公网安备 33010602011771号