- Synchronized和ReentrantLock的区别
实现级别:
synchronized是Java的一个关键字,属于JVM层面的原生支持,它通过监视器锁(Monitor)来实现同步控制,无需手动获取和释放锁。
ReentrantLock是java.util.concurrent包下的一个类,是API层面的实现,需要手动调用lock()方法获取锁,以及unlock()方法释放锁,提供了更灵活的锁操作。
可中断性:
synchronized锁不支持中断,一旦线程获得了锁,除非正常执行完毕或者抛出异常,否则无法中断。
ReentrantLock支持中断,调用lockInterruptibly()方法获取锁时,线程可以被其他线程中断并抛出InterruptedException。
公平性:
synchronized锁是非公平锁,它不保证等待时间最长的线程优先获取锁。
ReentrantLock既支持非公平锁也支持公平锁,通过构造函数可以选择锁的公平策略。
锁的尝试与超时:
synchronized没有直接提供尝试获取锁和超时获取锁的功能。
ReentrantLock提供了tryLock()方法尝试获取锁(可设置是否带超时时间),这使得线程在无法立即获取锁时不必阻塞,提高了效率和灵活性。
条件变量:
synchronized可以使用wait()、notify()、notifyAll()方法来协调线程间的通信,但这些方法与锁绑定且较为基础。
ReentrantLock通过Condition接口提供了更强大的线程间协调能力,每个Condition对象都和一个锁关联,可以更精确地控制多线程的等待通知机制。
性能:
在早期版本中,synchronized性能较差,但自从Java 6以来,JVM对其进行了大量优化,如偏向锁、轻量级锁等机制,使得其性能与ReentrantLock接近,在某些场景下甚至优于后者。
ReentrantLock通常被认为在高竞争环境下性能更优,尤其是当需要上述高级特性时。
异常处理:
使用synchronized时,如果同步代码块中发生异常,JVM会确保锁被自动释放,减少了死锁的风险。
使用ReentrantLock时,必须在finally块中显式调用unlock()方法来释放锁,以防止异常导致的锁泄露。
如果大家需要视频版本的讲解,欢迎关注我的B站: