hello啊,各位观众姥爷们!!!本baby今天又来报道了!哈哈哈哈哈嗝🐶
面试官:说说synchronized 和 ReentrantLock的区别?
synchronized
和 ReentrantLock
是 Java 中实现线程同步的两种机制,它们的主要区别如下:
1. 实现机制
- synchronized :是 Java 的关键字,基于 JVM 内置的监视器锁(Monitor)实现,自动加锁和释放锁。
- ReentrantLock :是
java.util.concurrent.locks
包下的一个类 ,基于 API 实现,依赖lock()
和unlock()
方法手动控制。
2. 锁的获取与释放
- synchronized :
自动管理锁的获取和释放,进入同步代码块时加锁,退出时(包括正常退出或抛出异常)自动释放锁。 - ReentrantLock :
必须显式调用lock()
加锁,并在finally
块中调用unlock()
释放锁,否则可能导致死锁。
3. 可中断性
- synchronized :
线程在等待锁时不可被中断,会一直阻塞直到获取锁。 - ReentrantLock :
支持通过lockInterruptibly()
实现可中断的锁等待,线程在等待时可以响应中断。
4. 公平性
- synchronized :
仅支持非公平锁(默认抢占式,不保证等待顺序)。 - ReentrantLock :
可通过构造函数选择公平锁或非公平锁(公平锁按等待顺序分配,减少线程饥饿)。
5. 功能扩展
- ReentrantLock 提供更灵活的功能:
- 尝试获取锁 :
tryLock()
可立即返回是否成功,或设置超时时间(tryLock(long timeout, TimeUnit unit)
)。 - 绑定多个条件变量 :通过
newCondition()
创建多个Condition
对象,实现更细粒度的线程通信(如生产者-消费者模型)。
- 尝试获取锁 :
- synchronized :
仅通过wait()
/notify()
实现单一条件的线程通信。
6. 性能
- JDK 1.6 之前 :
ReentrantLock
性能优于synchronized
。 - JDK 1.6 及之后 :
synchronized
引入偏向锁、轻量级锁等优化,两者性能差距不大。多数场景下优先使用synchronized
(简单、稳定)。
7. 可重入性
- 两者均为可重入锁:同一线程可重复获取同一把锁,避免死锁。
8. 异常处理
- synchronized :
发生异常时自动释放锁,避免死锁。 - ReentrantLock :
需在finally
中手动释放锁,否则锁可能无法释放。
总结对比表
特性 | synchronized | ReentrantLock |
---|---|---|
实现方式 | JVM 内置关键字 | API 实现的类 |
锁释放 | 自动释放 | 需手动调用 unlock() |
可中断性 | 不支持 | 支持(lockInterruptibly() ) |
公平锁 | 仅非公平锁 | 可配置公平或非公平 |
条件变量 | 单一条件 | 支持多个条件(Condition ) |
尝试获取锁 | 不支持 | 支持(tryLock() ) |
性能 | JDK 1.6+ 优化后接近 | 高竞争场景下表现更好 |
代码简洁性 | 简单,自动管理 | 需手动控制,更复杂 |
使用场景建议
- 优先
synchronized
:简单同步需求,无需复杂功能时(代码简洁、维护方便)。 - 选择
ReentrantLock
:- 需要可中断锁、超时获取锁、公平锁等高级功能。
- 需要细粒度的条件控制(如多个等待队列)。
技术资料大全:https://pan.q删掉汉子uark.cn/s/aa7f2473c65b
