AQS(AbstractQueuedSynchronizer)介绍
- 抽象队列同步器AbstractQueuedSynchronizer,是用来构建锁或者其他同步组件的基础框架,AQS的设计是基于模板方法模式的,也就是说,使用者需要继承同步器并重写指定的方法。
接下来先看下关键源码
public abstract class AbstractQueuedSynchronizer {
private transient volatile Node head;
private transient volatile Node tail;
private volatile int state;
tatic final class Node {
/** Marker to indicate a node is waiting in shared mode */
static final Node SHARED = new Node();
/** Marker to indicate a node is waiting in exclusive mode */
static final Node EXCLUSIVE = null;
/** waitStatus value to indicate thread has cancelled */
static final int CANCELLED = 1;
/** waitStatus value to indicate successor's thread needs unparking */
static final int SIGNAL = -1;
/** waitStatus value to indicate thread is waiting on condition */
static final int CONDITION = -2;
/**
* waitStatus value to indicate the next acquireShared should
* unconditionally propagate
*/
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;
}
}
protected final boolean compareAndSetState(int expect, int update) {
// See below for intrinsics setup to support this
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
}
源码解读:
-
使用了一个int成员变量state来表示同步锁状态,通过内置的FIFO(first-in-first-out)同步队列来控制获取共享资源的线程。请求线程都被封装成Node 节点。
-
内部state 和Node 内部类的属性都被volatile 关键字修饰,在修改state 和 阻塞队列时 都使用CAS机制循环添加,保证并发安全。
-
所以可以说AQS就是利用volatile 和CAS的实现
-
线程的阻塞方法都是使用的unsafe类进行的。
-
内置的三个修改同步状态的方法
- int getState() :获取当前同步状态
- void setState(int newState) :设置当前同步状态
- boolean compareAndSetState(int expect, int update) 使用CAS设置当前状态。
-
子类可以重写的方法
- boolean isHeldExclusively():当前线程是否独占锁
- boolean tryAcquire(int arg):独占式尝试获取同步状态,通过CAS操作设置同步状态,如果成功返回true,反之返回false,获取同步状态失败,就会通过CAS方式加入队列
- boolean tryRelease(int arg):独占式释放同步状态。
- int tryAcquireShared(int arg):共享式的获取同步状态,返回大于等于0的值,表示获取成功,反之失败。
- boolean tryReleaseShared(int arg):共享式释放同步状态。
-
进入到队列后,线程的阻塞和唤醒是使用的
LockSupport
的park
和unpark
方法来实现的。 -
比如我们继续深入理解一下AQS的实现类
- ReentrantLock [riːˈɛntrənt]
- 上锁的 lock 方法,重写了 tryAcquire,tryAcquire 内部 通过compareAndSetState 方法把 state 设置为1,设置失败,则加入队列,然后调用``LockSupport
.park()
阻塞线程 - unlock 的方法是重写了 tryRelease 方法,使用compareAndSetState 方法修改状态,使用LockSupport.unpark() 来取消阻塞
- ReentrantLock 内部实现了两种,公平锁和非公平锁的实现
- 公平锁先判断队列
- 非公平锁直接先修改状态,失败进入队列
- 上锁的 lock 方法,重写了 tryAcquire,tryAcquire 内部 通过compareAndSetState 方法把 state 设置为1,设置失败,则加入队列,然后调用``LockSupport
- CountDownLatch
- 这个在在新建对象的时候是把state 设置为指定值
- 调用wait()方法 ,内部实现 tryAcquireShared 获取共享锁,只要 是state 不为0,则获取成功
- 然后不断调用 countDown() 方法,内部实现 tryReleaseShared,一直怼state 做减操作,直到0
- state 到0 后 循环队列,调用LockSupport.unpark()
- ReentrantLock [riːˈɛntrənt]