ReentrantLock 跟 Synchronized 区别
面试回答:
相同点:
-
synchronized 和 ReentrantLock 都是用来保护资源线程安全的。
-
都可以保证可见性。
-
synchronized 和 ReentrantLock 都拥有可重入的特点。
从基本语义和概念上说
-
synchronized: Java 内建的同步机制 提供互斥性和可见性。 当一个线程获取锁后、其他线程只能等待或阻
synchronized 依赖 JVM 实现、使用更简单、由 JVM 负责锁的获取和释放。
-
ReentrantLock: Java 5 提供的锁实现。 通过lock()方法显式获取锁,unlock()方法显式释放锁。
但需要手动释放锁、否则可能导致死锁。一般会把unlock操作放入finally块来解锁、以防忘记解锁。
从锁的公平性来说:
-
ReentrantLock允许创建公平锁 与非公平锁 -
synchronized始终是非公平锁。当锁被释放时、哪个等待线程能获取锁是不确定的、可能导致某些线程长时间等待(饥饿)。
从灵活性来说:也就是可中断获取锁
-
synchronized锁不够灵活:synchronized一个线程获取锁之后、其他线程想要获取锁只能等待、只能进入阻塞状态、直到持有锁的线程释放这个锁、可能这个等待过程会持续很久。 -
相比之下、ReentrantLock可以使用
lockInterruptibly方法、不想等了可以中断退出、避免无限期等待-
也可以尝试非阻塞获取锁 (超时获取):提供了尝试非阻塞获取锁的方法 (
tryLock()),可以立即返回是否成功获取锁。这使得线程可以根据情况决定是否继续等待
-
从实现条件变量 (Condition)来说
-
ReentrantLock提供了Condition接口,可以将wait()、notify()、notifyAll()等操作转化为对象行为。 -
Condition允许线程在特定条件满足时挂起、并在条件满足时被唤醒。 -
ReentrantLock典型的应用场景是阻塞队列 (如ArrayBlockingQueue)、用于实现生产者-消费者模式。
从性能来说:(面试可以不回答 感觉没必要)
-
早期版本的
synchronized性能较差。 -
Java 6 之后,
synchronized进行了大量优化 (如锁膨胀、偏向锁、轻量级锁等)在低竞争情况下性能可能优于ReentrantLock。 -
在高竞争情况下,
ReentrantLock仍然可能具有一定优势
选择建议
-
synchronized: 优先考虑、尤其是在简单同步场景下、代码更简洁、且由 JVM 管理锁的释放、更安全。
-
ReentrantLock: 当需要公平锁、可中断锁、超时锁,或者需要使用多个条件变量时、选择 ReentrantLock。
