Java 的 AbstractQueuedSynchronizer(AQS)是一个用于构建同步器(如锁和信号量)的框架。它提供了一种实现线程同步的机制,通过管理一个先进先出(FIFO)的线程等待队列来控制对共享资源的访问。ReentrantLock 是基于 AQS 实现的一个可重入锁。下面我将详细解释 AQS 的原理以及 ReentrantLock 的实现方法。
![图片[1]_深入理解 Java AQS:ReentrantLock 的底层实现详解_知途无界](https://zhituwujie.com/wp-content/uploads/2025/03/d2b5ca33bd20250326093631.png)
AQS 原理
- 状态(State):
- AQS 内部维护一个
state
变量,用于表示共享资源的使用状态。子类通过实现特定的方法来管理这个状态。 - 对于独占模式,
state
为 0 表示资源可用,大于 0 表示资源被占用。 - 对于共享模式,
state
的具体含义由子类定义,但通常用于表示可用资源的数量。
- AQS 内部维护一个
- 等待队列(CLH 队列):
- AQS 使用一个双向链表来管理等待获取资源的线程。
- 每个节点包含线程引用、等待状态等信息。
- 线程在获取资源失败时会被封装成一个节点并加入队列尾部。
- 独占模式和共享模式:
- 独占模式:只有一个线程能获取资源,如 ReentrantLock。
- 共享模式:多个线程可以同时获取资源,如 Semaphore 和 CountDownLatch。
- 模板方法:
- AQS 提供了一些需要子类实现的模板方法,如
tryAcquire
、tryRelease
、tryAcquireShared
、tryReleaseShared
等。 - 子类通过实现这些方法定义具体的同步策略。
- AQS 提供了一些需要子类实现的模板方法,如
ReentrantLock 实现方法
ReentrantLock 是一个可重入的独占锁,基于 AQS 实现。以下是其关键实现点:
- 状态管理:
- ReentrantLock 使用 AQS 的
state
变量来表示锁的重入次数。 - 初始状态为 0,表示锁未被占用。每次获取锁时,
state
加 1;每次释放锁时,state
减 1。
- ReentrantLock 使用 AQS 的
- 获取锁(
lock()
方法):- 调用 AQS 的
acquire
方法,尝试获取锁。 tryAcquire
方法在 ReentrantLock 中被实现为:如果当前线程是锁的持有者,则增加重入计数并返回成功;否则,检查锁是否可用,若可用则设置锁的持有者为当前线程并返回成功。
- 调用 AQS 的
- 释放锁(
unlock()
方法):- 调用 AQS 的
release
方法,尝试释放锁。 tryRelease
方法在 ReentrantLock 中被实现为:减少重入计数,如果计数为 0,则释放锁并返回成功。
- 调用 AQS 的
- 非公平锁与公平锁:
- 非公平锁:线程在尝试获取锁时,可能会直接插队获取锁,而不是按照等待队列的顺序。
- 公平锁:线程严格按照等待队列的顺序获取锁。
- 通过构造函数可以选择使用非公平锁或公平锁。
示例代码
以下是一个简单的 ReentrantLock 使用示例:
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockExample {
private final ReentrantLock lock = new ReentrantLock();
public void performTask() {
lock.lock();
try {
// 临界区代码
System.out.println(Thread.currentThread().getName() + " is executing.");
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
ReentrantLockExample example = new ReentrantLockExample();
Runnable task = example::performTask;
Thread thread1 = new Thread(task, "Thread-1");
Thread thread2 = new Thread(task, "Thread-2");
thread1.start();
thread2.start();
}
}
在这个示例中,ReentrantLock
用于确保同一时间只有一个线程可以执行 performTask
方法中的临界区代码。
© 版权声明
文中内容均来源于公开资料,受限于信息的时效性和复杂性,可能存在误差或遗漏。我们已尽力确保内容的准确性,但对于因信息变更或错误导致的任何后果,本站不承担任何责任。如需引用本文内容,请注明出处并尊重原作者的版权。
THE END
暂无评论内容