目录
1. AQS简介
AQS
(AbstractQueuedSynchronizer)是JUC并发包中的一个核心类,它提供了一种实现同步器的框架,如ReentrantLock
、Semaphore
、CountDownLatch
、CyclicBarrier
等都是基于AQS
实现的。
AQS
的核心思想是维护一个双向链表,其中链表的每个节点都表示一个线程,线程通过竞争锁来加入到链表中,当锁被释放时,链表中的下一个线程可以获取到锁。同时,AQS
还提供了Condition
接口,用于实现等待/通知机制。
2. AQS的工作原理
- AQS内部维护了一个state变量,用来表示当前共享资源的状态。当有线程请求获取锁时,如果锁没有被其他线程占用,则该线程可以直接获取到锁;否则,该线程会被加入到等待队列中,等待锁的释放。
- 当锁被释放时,AQS会从等待队列中取出一个线程,并将锁的状态分配给该线程,使其获得锁。如果等待队列中还有其他线程,则继续从队列中取出线程,并分配锁的状态,直到队列为空或者锁的状态无法分配为止。
2.1 AQS的基本结构
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements Serializable {
private static final long serialVersionUID = 7373984972572414691L;
protected AbstractQueuedSynchronizer() { }
static final class Node {
static final Node SHARED = new Node();
static final Node EXCLUSIVE = null;
static final int CANCELLED = 1;
static final int SIGNAL = -1;
static final int CONDITION = -2;
static final int PROPAGATE = -3;
volatile int waitStatus;
volatile Node prev;
volatile Node next;
volatile Thread thread;
Node nextWaiter;
final boolean isShared() {
return nextWaiter == SHARED;
}
final Node predecessor() throws NullPointerException {
Node p = prev;
if (p == null)
throw new NullPointerException();
else
return p;
}
Node() {
}
Node(Thread thread, Node mode) {
this.nextWaiter = mode;
this.thread = thread;
}
Node(Thread thread, int waitStatus) {
this.waitStatus = waitStatus;
this.thread = thread;
}
}
private transient volatile Node head;
private transient volatile Node tail;
private volatile int state;
protected final int getState() {
return state;
}
protected final void setState(int newState) {
state = newState;
}
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
private transient Thread exclusiveOwnerThread;
protected final Thread getExclusiveOwnerThread() {
return exclusiveOwnerThread;
}
protected final void setExclusiveOwnerThread(Thread thread) {
exclusiveOwnerThread = thread;
}
}
AQS
的基本结构包括三部分:
Node
类:表示双向链表中的节点,每个节点代表一个线程。head
和tail
:分别表示链表的头和尾。state
:表示同步状态,不同的同步器可以使用state
表示不同的含义。
2.2 Node类
Node
类是AQS
中非常重要的一个类,它表示双向链表中的节点,每个节点代表一个线程。
static final class Node {
static final Node SHARED = new Node();
static final Node EXCLUSIVE = null;
static final int CANCELLED = 1;
static final int SIGNAL = -1;
static final int CONDITION = -2;
static final int PROPAGATE = -3;
volatile int waitStatus;
volatile Node prev;
volatile Node next;
volatile Thread thread;
Node nextWaiter;
final boolean isShared() {
return nextWaiter == SHARED;
}
final Node predecessor() throws NullPointerException {
Node p = prev;
if (p == null)
throw new NullPointerException();
else
return p;
}
Node() {
}
Node(Thread thread, Node mode) {
this.nextWaiter = mode;
this.thread = thread;
}
Node(Thread thread, int waitStatus) {
this.waitStatus = waitStatus;
this.thread = thread;
}
}
Node
类的主要属性包括:
waitStatus
:表示当前节点的等待状态,取值可能为CANCELLED
、SIGNAL
、CONDITION
、PROPAGATE
等。prev
和next
:表示链表中的前驱和后继节点。thread
:表示当前节点所代表的线程。nextWaiter
:表示下一个等待节点,对于独占模式下的节点,它总是为null
。
Node
类的主要方法包括:
isShared()
:判断当前节点是否为共享模式。predecessor()
:返回当前节点的前驱节点。
2.3 同步状态
同步状态是AQS
中非常重要的一个概念,不同的同步器可以使用state
表示不同的含义。例如,对于ReentrantLock
,state
表示获取锁的次数;对于Semaphore
,state
表示可用的许可证数量。
private volatile int state;
protected final int getState() {
return state;
}
protected final void setState(int newState) {
state = newState;
}
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
state
的修改使用了原子操作,compareAndSetState()
方法调用了unsafe.compareAndSwapInt()
方法。
2.4 独占模式下的同步器
独占模式下的同步器,例如ReentrantLock
,每次只允许一个线程获取锁。
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
protected boolean tryRelease(int arg) {
throw new UnsupportedOperationException();
}
protected int tryAcquireShared(int arg) {
throw new UnsupportedOperationException();
}
protected boolean tryReleaseShared(int arg) {
throw new UnsupportedOperationException();
}
protected boolean isHeldExclusively() {
throw new UnsupportedOperationException();
}
独占模式下的同步器需要实现tryAcquire()
、tryRelease()
、isHeldExclusively()
方法。
2.5 共享模式下的同步器
共享模式下的同步器,例如Semaphore
、CountDownLatch
、CyclicBarrier
,允许多个线程同时获取同一个锁。
protected int tryAcquireShared(int arg) {
throw new UnsupportedOperationException();
}
protected boolean tryReleaseShared(int arg) {
throw new UnsupportedOperationException();
}
共享模式下的同步器需要实现tryAcquireShared()
、tryReleaseShared()
方法。
2.6 等待队列
等待队列是AQS
中非常重要的一个概念,它是由Node
节点组成的双向链表,表示当前正在等待获取锁的线程。
private transient volatile Node head;
private transient volatile Node tail;
2.7 每个同步器的实现
2.7.1 CountDownLatch
CountDownLatch
是一个同步工具类,它允许一个或多个线程等待其他线程完成操作后再继续执行。
public class CountDownLatch {
private final Sync sync;
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
public void countDown() {
sync.releaseShared(1);
}
public long getCount() {
return sync.getCount();
}
public String toString() {
return super.toString() + "[Count = " + sync.getCount() + "]";
}
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
Sync(int count) {
setState(count);
}
int getCount() {
return getState();
}
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
protected boolean tryReleaseShared(int releases) {
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c-1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
}
}
CountDownLatch
的实现使用了AQS
,它继承了AbstractQueuedSynchronizer
类,并实现了Sync
内部类。
Sync
内部类继承了AbstractQueuedSynchronizer
类,并实现了tryAcquireShared()
、tryReleaseShared()
方法。
2.7.2 CyclicBarrier
CyclicBarrier
是一个同步工具类,它允许一组线程相互等待,直到所有线程都到达一个屏障点后再继续执行。
public class CyclicBarrier {
private final Sync sync;
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException("parties <= 0");
this.sync = new Sync(parties, barrierAction);
}
public CyclicBarrier(int parties) {
this(parties, null);
}
public int getParties() {
return sync.getParties();
}
public int await() throws InterruptedException, BrokenBarrierException {
return sync.acquireSharedInterruptibly(1);
}
public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
public boolean isBroken() {
return sync.isBroken();
}
public void reset() {
sync.reset();
}
private static class Generation {
boolean broken = false;
}
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 7684823728946441214L;
private final int parties;
private final Runnable barrierAction;
private Generation generation = new Generation();
Sync(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException("parties <= 0");
this.parties = parties;
this.barrierAction = barrierAction;
setState(parties);
}
int getParties() {
return parties;
}
boolean isBroken() {
return generation.broken;
}
void reset() {
setState(parties);
generation = new Generation();
}
protected int tryAcquireShared(int acquires) {
return doAcquireShared(acquires);
}
protected int tryReleaseShared(int releases) {
if (tryReleaseSharedImpl(releases)) {
return 1;
} else {
return -1;
}
}
private boolean tryReleaseSharedImpl(int releases) {
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c-1;
if (compareAndSetState(c, nextc)) {
if (nextc == 0) {
return true;
} else {
return false;
}
}
}
}
private int doAcquireShared(int acquires) {
final Node current = addWaiter(Node.SHARED);
boolean failed = true;
int remaining = -1;
try {
boolean interrupted = false;
for (;;) {
final Node p = current.predecessor();
if (p == head) {
int r = tryAcquireShared(acquires);
if (r >= 0) {
setHeadAndPropagate(current, r);
p.next = null;
if (interrupted) {
selfInterrupt();
}
failed = false;
return r;
}
}
if (shouldParkAfterFailedAcquire(p, current) && parkAndCheckInterrupt()) {
interrupted = true;
}
}
} finally {
if (failed) {
cancelAcquire(current);
}
}
}
private void setHeadAndPropagate(Node node, int propagate) {
Node h = head;
setHead(node);
if (propagate > 0 || h == null || h.waitStatus < 0 ||
(h = head) == null || h.waitStatus < 0) {
Node s = node.next;
if (s == null || s.isShared()) {
doReleaseShared();
}
}
}
private void doReleaseShared() {
for (;;) {
Node h = head;
if (h != null && h != tail) {
int ws = h.waitStatus;
if (ws == Node.SIGNAL) {
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0)) {
continue;
}
unparkSuccessor(h);
} else if (ws == 0 &&
!compareAndSetWaitStatus(h, 0, Node.PROPAGATE)) {
continue;
}
}
if (h == head) {
break;
}
}
}
private void cancelAcquire(Node node) {
if (node == null) {
return;
}
node.thread = null;
Node pred = node.prev;
while (pred.waitStatus > 0) {
node.prev = pred = pred.prev;
}
Node predNext = pred.next;
node.waitStatus = Node.CANCELLED;
if (node == tail && compareAndSetTail(node, pred)) {
compareAndSetNext(pred, predNext, null);
} else {
int ws;
if (pred != head &&
((ws = pred.waitStatus) == Node.SIGNAL ||
(ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
pred.thread != null) {
Node next = node.next;
if (next != null && next.waitStatus <= 0) {
compareAndSetNext(pred, predNext, next);
}
} else {
unparkSuccessor(node);
}
}
}
}
}
CyclicBarrier
的实现也使用了AQS
,它继承了AbstractQueuedSynchronizer
类,并实现了Sync
内部类。
Sync
内部类继承了AbstractQueuedSynchronizer
类,并实现了tryAcquireShared()
、tryReleaseShared()
方法。
3. 总结
AQS
是JUC并发包中的一个核心类,它提供了一种实现同步器的框架,如ReentrantLock
、Semaphore
、CountDownLatch
、CyclicBarrier
等都是基于AQS
实现的。
AQS
的核心思想是维护一个双向链表,其中链表的每个节点都表示一个线程,线程通过竞争锁来加入到链表中,当锁被释放时,链表中的下一个线程可以获取到锁。同时,AQS
还提供了Condition
接口,用于实现等待/通知机制。