Synchronized 相比,可重入锁 ReentrantLock 其实现原理有什么不同?
synchronized
和 ReentrantLock
是 Java 中两种常见的锁机制,它们都能实现线程同步,但它们的实现原理和使用方式有所不同。
- synchronized:
synchronized
是 Java 语言内置的关键字,用于控制多个线程对共享资源的访问。它在 JVM 层面实现了锁机制,不需要用户手动获取和释放锁。当一个线程进入 synchronized
块时,它会自动获取锁,并在退出 synchronized
块时自动释放锁。
synchronized
的实现原理与 JVM 的内部机制密切相关。当一个线程试图进入一个 synchronized
块时,JVM 会检查该对象是否被其他线程锁定。如果没有被锁定,该线程会获取锁并进入 synchronized
块。如果对象已经被其他线程锁定,那么该线程会被阻塞,直到锁被释放。
- ReentrantLock:
ReentrantLock
是 Java java.util.concurrent.locks
包中的一个类,它实现了 Lock
接口。ReentrantLock
是一种可重入锁,意味着一个线程可以多次获取同一个锁。与 synchronized
不同,ReentrantLock
需要用户手动获取和释放锁。
ReentrantLock
的实现原理是基于 AQS (AbstractQueuedSynchronizer) 框架。AQS 是一个用于构建锁和同步器的框架,它使用了一个内部的 FIFO 队列来管理等待获取锁的线程。当一个线程试图获取锁时,如果锁已经被其他线程持有,那么该线程会被放入 AQS 的等待队列中。当锁被释放时,等待队列中的线程会按照 FIFO 的顺序尝试获取锁。
主要区别:
- 获取和释放锁的方式:
synchronized
是自动获取和释放锁,而ReentrantLock
需要用户手动获取和释放锁。 - 等待可中断性:
ReentrantLock
提供了可中断的锁获取方式,而synchronized
不支持。 - 锁的释放: 在发生异常时,
synchronized
会自动释放锁,而ReentrantLock
需要通过unlock()
方法手动释放锁,否则可能导致死锁。 - 公平性和非公平性:
ReentrantLock
可以设置为公平锁或非公平锁,而synchronized
总是非公平的。
总的来说,synchronized
和 ReentrantLock
各有其特点和适用场景。在选择使用哪种锁时,需要根据具体的业务需求和性能要求来权衡。