AQS浅显理解
AQS (AbstractQueuedSynchronizer)
AQS
https://www.cnblogs.com/waterystone/p/4920797.html
美团技术AQS
https://tech.meituan.com/2019/12/05/aqs-theory-and-apply.html
1. AQS的数据结构

- FIFO双端队列结构(Node结构的双向链表形成, 每一个Node与一个线程进行绑定)
static final class Node {
static final Node SHARED = new Node();
static final Node EXCLUSIVE = null;
// waitStatus的四种状态
/*
0. 当一个Node被初始化的时候的默认值
1. CANCLEED:表示线程获取锁的请求已经取消了
2. SIGNAL:表示唤醒当前节点的后继节点。(eg:当前节点的prev.waitStatus == -1就表示其后继已经被唤醒。)
3. CONDITION:表示节点在条件等待队列(condition)中,节点线程等待唤醒
4. PROPAGATE:当前线程处在SHARED情况下,该字段才会使用. 共享模式下,前继结点不仅会唤醒其后继结点,同时也可能会唤醒后继的后继结点。
*/
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;
// 下一个节点。 这个是在条件condition队列中。
// 指向下一个处于CONDITION状态的节点
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() { // Used to establish initial head or SHARED marker
}
// Node mode表示模式(独占还是共享)
Node(Thread thread, Node mode) { // Used by addWaiter
this.nextWaiter = mode;
this.thread = thread;
}
Node(Thread thread, int waitStatus) { // Used by Condition
this.waitStatus = waitStatus;
this.thread = thread;
}
}
2. AQS 的主要使用方法
-
锁与释放锁调用的方法
- public final void acquire(int arg);// lock()方法调用。
- public final boolean release(int arg);// unlock()方法调用
-
针对独占锁
- protected boolean tryAcquire(int arg);// 需要AQS的子类自己重写。 尝试获取独占锁。 如果获取成功返回true。反之false
- protected boolean tryRelease(int arg);// 需要AQS的子类自己重写。尝试释放锁。如果获取成功返回true。反之false
-
针对共享锁
- protected int tryAcquireShared(int arg);// 尝试获取共享锁,arg表示获取锁的次数。 返回值——负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。
- protected boolean tryReleaseShared(int arg);// arg为释放锁的次数,尝试释放资源,如果释放后允许唤醒后续等待结点返回True,否则返回False。
AQS的独占模式的使用——————针对ReentrantLock的非公平方式分析
1. lock()方法
- 主要流程图
-
lock()总体步骤
![avatar]()
-
acquire()
![avatar]()
-
tryAcquire()
![avatar]()
-
addQueue()
![avatar]()
public class ReentrantLock implements Lock, java.io.Serializable {
private final Sync sync;
// lock.lock()首先调用这个方法
public void lock() {
sync.lock();// 这个调用的lock()方法是NonfairSync(Sync的子类)中的lock()方法
}
// Sync是一个继承了AQS的抽象类。 主要通过它来重写一些方法。比如tryAcquire()或者tryRelease().
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
abstract void lock();
// tryAcquire()方法实际调用的方法
final boolean nonfairTryAcquire(int acquires) {
// 获取当前线程
final Thread current = Thread.currentThread();
// 当前的状态。 初始状态是0, 每当获取锁状态+1
int c = getState();
if (c == 0) {
// 利用CAS来设置state的值
if (compareAndSetState(0, acquires)) {
// 这个方法是将独占锁的owner(拥有者)设置为当前线程
setExclusiveOwnerThread(current);
return true;
}
}
// 判断当前线程是否是 占有锁的线程。 如果是继续下去, 这里应该是针对可重入的使用
else if (current == getExclusiveOwnerThread()) {
// 更改state的值, 每当一个锁使用state+1
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
// 设置state
setState(nextc);
return true;
}
// 上述条件都不满足的话, 就表示获取锁失败
return false;
}
}
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
// lock()方法实际的调用
final void lock() {
// 尝试CAS, 看当前state的值是否为0。 如果是就将state的值更新为1. 然后将当前线程设置为 独占锁的线程
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
// 反之调用acquire()方法, 这是AQS父类中的方法, 见下面AQS
acquire(1);
}
// AQS中的acquire()中tryAcquire()调用的是该方法
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
}
// AQS
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
// Node节点的定义,见上面。
// 构造方法
protected AbstractQueuedSynchronizer() { }
// 队列的头部
private transient volatile Node head;
// 队列的尾部
private transient volatile Node tail;
// 状态值
private volatile int state;
// 给定了set和get方法
}
// 获取锁调用的方法
public final void acquire(int arg) {
// 其中tryAcquire()调用的是子类的tryAcquire()方法.分析是否获取到锁。如果没有获取到锁, 然后进行下面
// acquireQueued()方法的使用。中间调用addWaiter()方法
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
// 该方法将没有获取到锁线程加入到Node队列中等待
// 针对独占锁传入的mode就是Node.EXCLUSIVE也就是null
// 返回值:当前加入队列的节点
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
Node pred = tail;
// 这里表示队列中已经有了元素
if (pred != null) {
node.prev = pred;
// CAS改变tail的值
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
// enq(Node node)方法将node节点加入到队列中
// 这是CAS改变tail的值失败,或者是pred == null(也就是空队列)加入到队列中
enq(node);
return node;
}
// 这个方法的作用:不断的自旋,尝试来获取锁的使用权
final boolean acquireQueued(final Node node, int arg) {
// failed我认为
boolean failed = true;
try {
boolean interrupted = false;
// 自旋
for (;;) {
// node.predecessor()获取当前节点的前驱节点
final Node p = node.predecessor();
// 如果p节点是head节点,就表示node节点是该等待队列中的第二个节点。那么让它来尝试获取锁tryAcquire(arg)
// 从enq()方法可以看出head节点是一个相当于空节点的东西
if (p == head && tryAcquire(arg)) {
// 如果获取到了锁, 那么将node当前节点设置为head
setHead(node);
// 这个是为了帮助GC。 p节点是之前的head。 head.next = null就让head没有使用了
p.next = null; // help GC
failed = false;
return interrupted;
}
// 如果p不是head节点或者没有获取到锁。执行下面的步骤
// shouldParkAfterFailedAcquire(p, node):判断在获取锁失败之后是否应该park, 如果需要park执行parkAndCheckInterrupt()
// 如果该线程中断过就设置interrupted=true
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
// 当当前线程申请锁的请求被取消的话, 就将当前node节点的waistatus置为CANCELLED
} finally {
if (failed)
cancelAcquire(node);
}
}
// 返回值:true表示需要阻塞;false表示不用park
/*
参数值
* Node pred:node节点的前一个节点
* Node node当前节点
*/
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
// 前一个节点的状态
int ws = pred.waitStatus;
// 如果是SIGNAL表示node节点已经被唤醒了, 但是没获取到锁就park
if (ws == Node.SIGNAL)
return true;
// 如果 pred的waitStatus是 CANCELLED(表示线程获取锁的请求已经取消了)。不断的向前的找状态不是CANCELLED的节点
if (ws > 0) {
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
// CAS改变ws的值
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
// park()当前线程
// 返回值:该线程是否中断过
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
// 将当前节点设置为CANCELLED,从队列中移出。
private void cancelAcquire(Node node) {
// Ignore if node doesn't exist
if (node == null)
return;
// 将线程与该node解绑
node.thread = null;
// 跳过那些CANCELLED的前驱节点
Node pred = node.prev;
while (pred.waitStatus > 0)
node.prev = pred = pred.prev;
// node节点前驱的前驱
Node predNext = pred.next;
// 将node节点的状态置为CANCELLED
node.waitStatus = Node.CANCELLED;
// 如果当前节点node是tail节点。删除之后设置prev节点为新的tail节点
if (node == tail && compareAndSetTail(node, pred)) {
compareAndSetNext(pred, predNext, null);
} else {
int ws;
// 如果pred也就是当前节点node的前驱节点不是head。分两种情况
// 1. pred.waitStatus是否为Node.SIGNAL 2. CAS pred的ws是否能够成功
// 如果两种情况有一个为true那么就判断pred节点对应的线程是都为null
if (pred != head &&
((ws = pred.waitStatus) == Node.SIGNAL ||
(ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
pred.thread != null) {
Node next = node.next;
// 这里是利用CAS来将当前节点的前驱结点的next设置为 当前节点的后继节点
if (next != null && next.waitStatus <= 0)
compareAndSetNext(pred, predNext, next);
} else {
// 如果pred == head, 就尝试唤醒node节点的后继节点
unparkSuccessor(node);
}
node.next = node; // help GC
}
}
// unpark node节点的后继节点
private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
// 从后往前找 找到第一个ws < 0的节点
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
// 唤醒node的后继
LockSupport.unpark(s.thread);
}
// 将节点加入到Node队列中, 这个方法的返回值是当前节点的前一个节点
// 利用的是CAS的方法进行加入, 不断的循环
private Node enq(final Node node) {
for (;;) {
Node t = tail;
// 队列为空
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
2. unlock()方法
- 方法调用顺序流程图
![avatar]()
public class ReentrantLock implements Lock, java.io.Serializable {
public void unlock() {
sync.release(1);
}
abstract static class Sync extends AbstractQueuedSynchronizer {
// 省略
// tryRelease()调用这个方法。尝试来释放资源
// 返回值:true:释放成功
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
// 对于可重入锁,每次调用这个方法 state会--; 直到最后state == 0就释放锁
if (c == 0) {
free = true;
// 将锁释放,其拥有者置为null
setExclusiveOwnerThread(null);
}
// 修改state
setState(c);
return free;
}
}
}
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
// unpark(唤醒) head节点的后一个节点。
unparkSuccessor(h);
return true;
}
return false;
}
}

浙公网安备 33010602011771号