面试官:有了解过ReentrantLock的底层实现吗?说说看("面试必问:深入解析ReentrantLock底层实现原理")

原创
ithorizon 7个月前 (10-20) 阅读数 13 #后端开发

面试必问:深入解析ReentrantLock底层实现原理

一、ReentrantLock简介

ReentrantLock是Java中提供的一种显示锁机制,它实现了Lock接口,提供了比synchronized关键字更充裕的功能,如可中断的锁获取、尝试非阻塞地获取锁、赞成公平锁等。ReentrantLock的实现原理是基于Java的AQS(AbstractQueuedSynchronizer)框架。

二、AQS框架

AQS是Java并发包中一个非常核心的组件,它为ReentrantLock、CountDownLatch、Semaphore等并发工具提供了底层赞成。AQS框架的核心原理是利用了CLH队列(Craig, Landin, and Hagersten queue)来实现同步。

三、ReentrantLock的底层实现

ReentrantLock底层实现首要分为两部分:Sync类和NonfairSync类(非公平锁)和FairSync类(公平锁)。

3.1 Sync类

Sync类是ReentrantLock的内部类,它继承了AQS。Sync类提供了ReentrantLock的基本操作,如lock、unlock等。

public abstract static class Sync extends AbstractQueuedSynchronizer {

private static final long serialVersionUID = 6476155730509392570L;

protected Sync() {

}

abstract void lock();

final boolean nonfairTryAcquire(int acquires) {

final Thread current = Thread.currentThread();

int c = getState();

if (c == 0) {

if (compareAndSetState(0, acquires)) {

setExclusiveOwnerThread(current);

return true;

}

} else if (current == getExclusiveOwnerThread()) {

int nextc = c + acquires;

if (nextc < 0) {

throw new Error("Maximum lock count exceeded");

}

setState(nextc);

return true;

}

return false;

}

protected final boolean tryRelease(int releases) {

int c = getState() - releases;

if (c < 0) {

throw new IllegalMonitorStateException();

}

if (c == 0) {

setExclusiveOwnerThread(null);

return true;

}

return false;

}

}

3.2 NonfairSync类

NonfairSync类是Sync的子类,它实现了非公平锁的获取和释放操作。在NonfairSync中,lock方法直接调用AQS的acquire方法。

static final class NonfairSync extends Sync {

private static final long serialVersionUID = -871948314811505487L;

NonfairSync() {

}

final void lock() {

acquire(1);

}

protected final boolean tryAcquire(int acquires) {

return nonfairTryAcquire(acquires);

}

}

3.3 FairSync类

FairSync类也是Sync的子类,它实现了公平锁的获取和释放操作。在FairSync中,lock方法调用了AQS的acquire方法,但tryAcquire方法会有所不同。

static final class FairSync extends Sync {

private static final long serialVersionUID = -7284743614705905476L;

FairSync() {

}

final void lock() {

acquire(1);

}

protected final boolean tryAcquire(int acquires) {

final Thread current = Thread.currentThread();

int c = getState();

if (c == 0) {

if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) {

setExclusiveOwnerThread(current);

return true;

}

} else if (current == getExclusiveOwnerThread()) {

int nextc = c + acquires;

if (nextc < 0) {

throw new Error("Maximum lock count exceeded");

}

setState(nextc);

return true;

}

return false;

}

}

四、ReentrantLock的获取和释放锁流程

下面我们来分析一下ReentrantLock获取和释放锁的流程。

4.1 获取锁(lock方法)

当线程调用ReentrantLock的lock方法时,实际上会调用Sync类的acquire方法。acquire方法会尝试通过tryAcquire方法获取锁,如果获取未果,则会将当前线程加入到AQS的等待队列中。

public void lock() {

sync.acquire(1);

}

public final void acquire(int arg) {

if (!tryAcquire(arg) &&

acquireQueued(addWaiter(Node.EXCLUSIVE), arg))

selfInterrupt();

}

4.2 释放锁(unlock方法)

当线程调用ReentrantLock的unlock方法时,实际上会调用Sync类的release方法。release方法会尝试通过tryRelease方法释放锁,如果释放胜利,则会唤醒AQS队列中的下一个线程。

public void unlock() {

sync.release(1);

}

public final boolean release(int arg) {

if (tryRelease(arg)) {

Node h = head;

if (h != null && h.waitStatus != 0)

unparkSuccessor(h);

return true;

}

return false;

}

五、总结

ReentrantLock的实现原理是基于Java的AQS框架。通过Sync类和其子类NonfairSync和FairSync,ReentrantLock提供了公平锁和非公平锁的实现。获取锁的过程是通过tryAcquire方法尝试获取锁,如果未果则加入等待队列;释放锁的过程是通过tryRelease方法释放锁,并唤醒等待队列中的下一个线程。通过深入了解ReentrantLock的底层实现,我们可以更好地懂得并发编程中的锁机制,以及怎样高效地使用ReentrantLock来保证线程可靠。


本文由IT视界版权所有,禁止未经同意的情况下转发

文章标签: 后端开发


热门