前言
Provides a framework for implementing blocking locks and related synchronizers (semaphores, events, etc) that rely on first-in-first-out (FIFO) wait queues. This class is designed to be a useful basis for most kinds of synchronizers that rely on a single atomic int value to represent state.
这段话是AbstractQueuedSynchronizer源码注释中的一段,意思是AbstractQueuedSynchronizer(AQS抽象队列同步器)提供了一个基于FIFO等待队列来实现阻塞锁和相关同步器的框架,而且这个类对于很多种依赖于单个原子int值表示状态的同步器是一个很有用的基础。
简言之,AQS提供了一个框架来实现锁,通过一个原子int值表示加锁状态,阻塞的线程进入FIFO队列进行等待。
主要方法
private volatile int state;
// 获取state
protected final int getState() {
return state;
}
// 修改state
protected final void setState(int newState) {
state = newState;
}
// 通过CAS修改state
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
上面是state属性和相关方法,state表示同步器状态,也就是是否加锁或加锁次数。
protected boolean isHeldExclusively()
AQS对于资源的共享有两个种方式,分别是独占方式和共享方式。独占表示只有一个线程可以执行,其他线程只能等待;共享方式下多个线程都可以执行。isHeldExclusively表示是否在独占模式下被占用。
protected boolean tryAcquire(int arg)
尝试在独占模式下进行加锁。
protected int tryAcquireShared(int arg)
尝试在共享模式下进行加锁
protected boolean tryRelease(int arg)
尝试在独占模式下进行解锁
protected boolean tryReleaseShared(int arg)
尝试在共享模式下进行解锁
使用AQS的思路就是继承
AbstractQueuedSynchronizer类并实现以上操作锁(state)的方法就可以了。
应用举例
Java中很多同步器类都是通过AQS来实现的,比如ReentrantLock、CountDownLatch。
ReentrantLock实现原理是state初始值为0表示没有加锁,线程调用tryAcquire方法尝试获取锁,获取成功就把state修改为1,并把独占拥有者线程exclusiveOwnerThread属性值标记为当前线程,在持有锁期间还可以重复获取锁,每获取一次就把state加1,每释放一次锁就把state减1,这就是ReentrantLock类是可重入锁的原因,直到state为0时其他线程才能获取锁成功。锁释放前其他锁尝试获取锁失败,就会进入阻塞队列进行等待。
CountDownLatch的基本原理是初始化时把state设为n,每调用一次countDown方法就把state减1,所以当countDown次数和n相等时,state的值就是0了,就会唤醒主线程继续向下执行。