本文共 1729 字,大约阅读时间需要 5 分钟。
ReentrantLock(可重入锁)是Java中最常用的互斥锁之一。与synchronized的区别在于,ReentrantLock支持更高级的功能,例如可中断、公平锁以及多个条件变量的支持。它不仅在API层面实现了互斥锁的功能,还提供了更高级别的锁管理能力。
ReentrantLock默认使用非公平锁机制,但可以通过构造方法ReentrantLock(boolean fair)来指定使用公平锁。相比于synchronized,ReentrantLock在API和语法层面提供了更高的灵活性。
ReentrantLock的加锁过程主要通过其内部的同步机制来实现。非公平锁和公平锁的实现方式在于试锁(tryAcquire)和加锁(acquire)的逻辑有所不同。
ReentrantLock的非公平锁由NonfairSync实现。其核心逻辑如下:
final void lock() { if (compareAndSetState(0, 1)) { setExclusiveOwnerThread(Thread.currentThread()); } else { acquire(1); }}protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires);} 非公平锁的tryAcquire方法直接尝试修改锁状态,不会检查队列中是否有等待的线程。这使得非公平锁在高并发场景下表现更优,但可能导致某些线程长时间等待。
公平锁由FairSync实现。其加锁逻辑如下:
final void lock() { acquire(1);} public的tryAcquire方法在尝试获取锁时,会先检查队列中是否有前驱节点。如果没有,则直接尝试获取锁;如果有,则进入队列等待。
当一个线程尝试获取锁时,会执行tryAcquire逻辑:
ReentrantLock的解锁过程与加锁过程相反。它主要通过释放锁的状态,并 唤醒等待的线程。
当一个线程释放锁时,会执行以下步骤:
ReentrantLock支持锁重入,通过在获取锁时递增锁的计数器来实现。当线程再次尝试获取锁时,会检查当前线程是否仍然持有锁,若是则递增计数器,否则进入队列等待。
ReentrantLock允许线程在加锁过程中被打断。对于非公平锁,打断不会导致线程立即退出,而是继续等待锁的状态。对于公平锁,打断会导致线程立即退出并抛出InterruptedException异常。
ReentrantLock支持绑定多个条件变量(Condition),通过Condition对象的await()方法实现线程等待。具体实现逻辑如下:
通过这种方式,ReentrantLock允许线程在不同的条件下进行互相唤醒,实现更复杂的同步逻辑。
ReentrantLock作为Java中的互斥锁,提供了高级功能,适用于多线程环境下的同步控制。其核心逻辑在于通过AQS(AbstractQueuedSynchronizer)实现队列管理和锁状态控制。通过非公平锁和公平锁的选择,以及多个条件变量的支持,ReentrantLock在高并发场景下提供了更高效的同步解决方案。
转载地址:http://fgvfk.baihongyu.com/