前言
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
了,就会唤醒主线程继续向下执行。