AQS(AbstractQueuedSynchronizer)是Java并发包java.util.concurrent
中提供的一个用于构建锁和其他同步组件的框架。它使用一个int成员变量来表示同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作。
核心概念
同步状态(State)
AQS内部维护一个volatile的int类型的state变量,用来表示同步状态。不同的同步组件对state的使用方式不同。例如,ReentrantLock用它来表示持有锁的次数,Semaphore用它来表示可用的许可证数量。
节点(Node)和队列(FIFO)
AQS内部使用了一个名为Node的内部类来表示等待的线程。当线程尝试获取资源失败时,会被封装为Node节点加入到AQS的队列中。AQS使用一个双向链表(FIFO队列)来管理这些节点,确保资源分配的公平性和效率。
独占模式与共享模式
AQS支持两种同步模式:独占模式和共享模式。独占模式下,资源的访问被限制在一个线程,如ReentrantLock。共享模式下,资源可以被多个线程同时访问,如Semaphore和CountDownLatch。
AQS的同步组件实现
AQS提供了一系列模板方法,同步组件通过继承AQS并实现这些模板方法来管理同步状态。
独占模式下的同步组件实现
以下是一个简化的ReentrantLock实现,展示了如何利用AQS实现独占模式下的同步组件:
public class Mutex extends AbstractQueuedSynchronizer {
// 抢占资源(锁)
protected boolean tryAcquire(int acquires) {
assert acquires == 1; // Otherwise unused
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
// 释放资源(锁)
protected boolean tryRelease(int releases) {
assert releases == 1; // Otherwise unused
if (getState() == 0) throw new IllegalMonitorStateException();
setExclusiveOwnerThread(null);
setState(0);
return true;
}
// 是否被占用
public boolean isLocked() {
return getState() != 0;
}
// 提供一个锁
public Lock newCondition() {
return new ConditionObject();
}
}
在上述代码中,tryAcquire
用于尝试获取锁,tryRelease
用于尝试释放锁。这些方法覆盖了AQS中的模板方法,并实现了锁的获取与释放。
共享模式下的同步组件实现
下面是一个简化的CountDownLatch的实现,展示了如何利用AQS实现共享模式下的同步组件:
public class SharedCountDownLatch extends AbstractQueuedSynchronizer {
public SharedCountDownLatch(int count) {
setState(count);
}
public void countDown() {
for (;;) {
int c = getState();
if (c == 0 || compareAndSetState(c, c - 1)) {
if (c == 1) {
releaseShared(1);
}
break;
}
}
}
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
for (;;) {
int c = getState();
if (c == 0) {
return false;
}
int nextc = c - 1;
if (compareAndSetState(c, nextc)) {
return nextc == 0;
}
}
}
}
在上述代码中,tryAcquireShared
和tryReleaseShared
方法被实现来管理同步状态。countDown
方法用于减少计数,当计数到0时,会释放所有等待的线程。
AQS的重要方法
AQS定义了一系列的方法来进行同步状态管理,这些方法可以分为三类:
-
独占模式下的获取与释放
acquire(int arg)
release(int arg)
-
共享模式下的获取与释放
acquireShared(int arg)
releaseShared(int arg)
-
查询同步状态
int getState()
void setState(int newState)
boolean hasQueuedThreads()
总结
AQS是构建锁和其他同步组件的强大框架。它利用volatile变量state来控制同步状态,并通过内部的双向链表来维护等待获取资源的线程队列。通过扩展AQS并实现相关的获取和释放方法,可以构建出各种同步组件。实际上,JDK中许多高级同步类,如ReentrantLock、Semaphore、CountDownLatch等,都是基于AQS构建的。