AQS原理
外观
AQS(AbstractQueuedSynchronizer)是Java并发编程中构建锁和同步器的核心框架,位于`java.util.concurrent.locks`包下。它为开发者提供了基于FIFO队列的阻塞锁和同步器的实现模板,是理解`ReentrantLock`、`Semaphore`、`CountDownLatch`等工具的基础。
概述[编辑 | 编辑源代码]
AQS通过一个volatile int state变量表示同步状态,并通过内置的FIFO双向队列管理竞争线程的排队工作。其核心思想是:
- 如果共享资源空闲,线程直接获取资源并修改状态;
- 如果资源被占用,线程进入队列阻塞等待,直到被前驱节点唤醒。
AQS支持独占模式(如`ReentrantLock`)和共享模式(如`Semaphore`),开发者只需重写`tryAcquire`、`tryRelease`等方法即可实现自定义同步器。
核心结构[编辑 | 编辑源代码]
同步状态(state)[编辑 | 编辑源代码]
通过`volatile int state`表示资源状态,子类通过CAS操作修改它:
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
同步队列[编辑 | 编辑源代码]
使用CLH变体的双向队列管理阻塞线程,节点类型为`Node`:
关键方法[编辑 | 编辑源代码]
AQS提供模板方法供子类实现:
- 独占模式:
* `tryAcquire(int arg)`:尝试获取资源。 * `tryRelease(int arg)`:尝试释放资源。
- 共享模式:
* `tryAcquireShared(int arg)`:尝试共享获取。 * `tryReleaseShared(int arg)`:尝试共享释放。
代码示例:自定义互斥锁[编辑 | 编辑源代码]
以下是一个基于AQS的简单互斥锁实现:
class Mutex extends AbstractQueuedSynchronizer {
@Override
protected boolean tryAcquire(int arg) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
@Override
protected boolean tryRelease(int arg) {
if (getState() == 0) throw new IllegalMonitorStateException();
setExclusiveOwnerThread(null);
setState(0);
return true;
}
public void lock() { acquire(1); }
public void unlock() { release(1); }
}
// 使用示例
public class Main {
public static void main(String[] args) {
Mutex mutex = new Mutex();
new Thread(() -> {
mutex.lock();
System.out.println("Thread1 acquired lock");
mutex.unlock();
}).start();
new Thread(() -> {
mutex.lock();
System.out.println("Thread2 acquired lock");
mutex.unlock();
}).start();
}
}
输出:
Thread1 acquired lock Thread2 acquired lock
实际应用场景[编辑 | 编辑源代码]
- `ReentrantLock`:通过AQS实现可重入的独占锁。
- `Semaphore`:使用AQS管理共享资源的许可数量。
- `CountDownLatch`:利用AQS同步多个线程的完成状态。
数学原理[编辑 | 编辑源代码]
AQS的队列调度遵循公平性与效率的权衡。设队列长度为,则:
- 非公平锁的竞争时间复杂度为(可能插队)。
- 公平锁的竞争时间复杂度为(严格排队)。
总结[编辑 | 编辑源代码]
AQS是Java并发包的基石,其设计精妙之处在于: 1. 通过模板方法模式分离通用逻辑与具体实现。 2. 利用CLH队列减少锁竞争的开销。 3. 支持灵活的自定义同步策略。
理解AQS原理后,可以更高效地使用Java并发工具,并能够根据业务需求设计高性能同步器。