AQS源码分析
场景模拟:
假如有三个线程 A B C , 而A线程先抢到了线程而且将后面的线程阻塞了很长时间
-
首先来到ReentrantLock 的 205 行 当前是第一次抢夺线程来到这个方法
final void lock() {
// state的默认值是0 获取到当前的值比较并交换是否为0如果是就更新为1
// 因为线程A是第一个来抢夺的所有满足条件
if (compareAndSetState(0, 1))
// 进入判断 将当前线程设置为一个排他锁
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
至此线程A执行完毕并且 state 的状态变为了 1
-
当第二个线程B进来抢夺线程同样首先来到这里
final void lock() { // 对state的值比较并交换 如果当前的state值为0就更新为1 // 因为在A线程占到位置以后就把state的值修改为了 1 // 所以本次判读失败直接进入else if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else // 线程B修改state值失败进入else逻辑 acquire(1); }
-
点击进入 acquire(1); 方法
public final void acquire(int arg) { // 当前的arg值为 1 是上一步传入进来的 // 首先进入到 tryAcquire(arg) 方法 if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
-
进入到 tryAcquire(arg) 方法 然后来到 nonfairTryAcquire
final boolean nonfairTryAcquire(int acquires) { // acquires 值为1 是上面方法传入进来的
final Thread current = Thread.currentThread(); // current 即为当前线程B
int c = getState(); // c为当前的state 值为1
if (c == 0) { // 当前c值为1 所以直接进入else if
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
// 来到else if 判断当前的线程是否为 正在执行操作的线程
// 当前线程为 B 正在执行操作的线程为 A 所以无法进入当前逻辑 直接到最后返回false
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
// 由于上面判断都无法成功所以直接返回false
return false;
}
-
由于 step_4 执行完以后返回为 false 再次来到 step_3 进入下一个方法的逻辑
public final void acquire(int arg) { if (!tryAcquire(arg) && // tryAcquire(arg); 返回为false 取反 为 true // 由于括号的优先级最高所以先进入括号内的 addWaiter(Node.EXCLUSIVE) 方法 // 点进源码可知 Node.EXCLUSIVE 默认值为null 所以传递进去的也为null acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
-
来到 addWaiter(Node.EXCLUSIVE) 方法
private Node addWaiter(Node mode) { // 当前 mode 的值为 null // 将当前线程包装成一个 Node 节点 Node node = new Node(Thread.currentThread(), mode); // Try the fast path of enq; backup to full enq on failure Node pred = tail; // aqs有头尾指针默认为null 将tail 赋值给 pred if (pred != null) { // 此判断无法进入 所以直接进入到 方法 enq(node) node.prev = pred; if (compareAndSetTail(pred, node)) { pred.next = node; return node; } } enq(node); // 来到这个方法 下图的 线程B 即为 node return node; }
-
来到 enq node 的值即为上图的线程B
private Node enq(final Node node) { // node 的值为 上图的线程B 然后进入cas
for (;;) {
Node t = tail; // ①一个新的节点 也指向 null
// ②当前t为新创建的哨兵节点不为null,直接进入else
if (t == null) { // Must initialize // ①当前的 t 为null 所以可以进入
// ①创建出一个新的节点但是没有内容,并设置为头节点 如下图
if (compareAndSetHead(new Node()))
tail = head; // ①将tail 也指向新创建的节点
} else {
// 最终效果如下第二张图
// 第二次循环直接来到else
// 将 线程B的前驱节点指向t也就是哨兵节点
node.prev = t;
// 比较并交换尾节点 当前的尾节点为 t 所以此处为true
if (compareAndSetTail(t, node)) {
// 将 哨兵节点的下一个指向线程B
t.next = node;
return t;
}
}
}
}
-
回到 step_5
public final void acquire(int arg) { if (!tryAcquire(arg) && // tryAcquire(arg); 返回为false 取反 为 true // 由于括号的优先级最高所以先进入括号内的 addWaiter(Node.EXCLUSIVE) 方法 // 点进源码可知 Node.EXCLUSIVE 默认值为null 所以传递进去的也为null // addWaiter(Node.EXCLUSIVE) 方法最终返回Node包装的线程B // 然后进入到 acquireQueued 方法 acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
-
来到 acquireQueued() 方法
// node为线程B , arg 为 1 final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { boolean interrupted = false; for (;;) { // 点进 predecessor 可知 // p的值为 当前线程B节点的前一个节点 也就是 哨兵节点 // 第二次循环 // p还是哨兵节点 final Node p = node.predecessor(); // p为哨兵节点head也为哨兵节点 所以第一个判断为true // 第二个判断arg让B线程再次抢夺一下 最终为 false // 所以进入到 下一个if // 第二次循环跟第一次一样还是无法进入直接来到第二个if if (p == head && tryAcquire(arg)) { setHead(node); p.next = null; // help GC failed = false; return interrupted; } // 来到这个判断进入到 step_10 // p 为哨兵节点 node 为线程B // 第一个为false 所以直接退出第一次循环 // 第二次循环 再次来到 step_10 // 第一个判断为true if (shouldParkAfterFailedAcquire(p, node) && // 此方法来到step_11 可知 将当前线程B被挂起 parkAndCheckInterrupt()) interrupted = true; } } finally { if (failed) cancelAcquire(node); } }
-
shouldParkAfterFailedAcquire()
// pred为哨兵节点 node 为线程B private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) { // 第一次来到此方法ws为哨兵节点的waitStatus 为 0 // 第二次来到此方法ws为哨兵节点的waitStatus 为 -1 int ws = pred.waitStatus; // 下面的判断都不满足 直接进入到else // 第二次进入此方法 // 满足条件返回true 回到step_9 if (ws == Node.SIGNAL) // SIGNAL 为 -1 /* * This node has already set status asking a release * to signal it, so it can safely park. */ return true; if (ws > 0) { /* * Predecessor was cancelled. Skip over predecessors and * indicate retry. */ do { node.prev = pred = pred.prev; } while (pred.waitStatus > 0); pred.next = node; } else { /* * waitStatus must be 0 or PROPAGATE. Indicate that we * need a signal, but don't park yet. Caller will need to * retry to make sure it cannot acquire before parking. */ // 比较并赋值 将 哨兵节点的 waitStatus 设置为 -1 最终返回false compareAndSetWaitStatus(pred, ws, Node.SIGNAL); } return false; }
-
parkAndCheckInterrupt()
private final boolean parkAndCheckInterrupt() { LockSupport.park(this); return Thread.interrupted(); }
第二个线程完毕 接下来是第三个线程
-
来到非公平的lock锁 依然是进入到 acquire(1);
final void lock() { if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); // step_2 }
-
acquire()
// arg 的值为 1 public final void acquire(int arg) { if (!tryAcquire(arg) && // 依然是无法获取到资源 返回false 取反 为true // acquireQueued step_4 addWaiter() step_3 返回一个线程C的node节点 acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
-
addWaiter()
// 当前mode 为线程C private Node addWaiter(Node mode) { // 将线程C封装成一个Node Node node = new Node(Thread.currentThread(), mode); // Try the fast path of enq; backup to full enq on failure Node pred = tail; // 当前tail为 线程B 所以 prev 也为 线程B if (pred != null) {// 满足判断进入逻辑 node.prev = pred; // 将线程C的前驱节点指向 线程B if (compareAndSetTail(pred, node)) { // 比较并设置尾巴节点将尾巴节点指向线程C pred.next = node; // 将线程B的next指向线程C return node; // 直接返回node } } enq(node); // step_4 return node; }
-
acquireQueued()
// node 的值为 线程C , arg 的值为 1
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
// p 的值为 线程C的前一个节点 B 节点
final Node p = node.predecessor();
// p != head 来到第二个if
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
// 第一个条件见 step_5
if (shouldParkAfterFailedAcquire(p, node) &&
// 将线程C挂起
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
-
// pred 为 线程线程B , node为线程C private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) { int ws = pred.waitStatus; // ws = 0 // 直接来到else if (ws == Node.SIGNAL) // SIGNAL的值为-1不满足 /* * This node has already set status asking a release * to signal it, so it can safely park. */ return true; if (ws > 0) { /* * Predecessor was cancelled. Skip over predecessors and * indicate retry. */ do { node.prev = pred = pred.prev; } while (pred.waitStatus > 0); pred.next = node; } else { /* * waitStatus must be 0 or PROPAGATE. Indicate that we * need a signal, but don't park yet. Caller will need to * retry to make sure it cannot acquire before parking. */ // 将线程B的waitStatus 的值设置为 -1 compareAndSetWaitStatus(pred, ws, Node.SIGNAL); } return false; }
到此我们的入队就完成了,接下来是出队,下图为入队后的图例
-
来到unlock() 的方法进入到 sync.release(1); 方法
// arg 的值为 1 public final boolean release(int arg) { // 尝试释放 tryRelease 方法 看 step_2 // 返回为true 进入判断 if (tryRelease(arg)) { // h = 哨兵节点 Node h = head; // 第一个满足 && 第二个满足 if (h != null && h.waitStatus != 0) // unparkSuccessor(h) 方法看 step_3 unparkSuccessor(h); return true; } return false; }
-
tryRelease(int releases);
// releases 的值为 1 protected final boolean tryRelease(int releases) { // 当前的 state 为 1 所以 c的值为 0 int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); // 默认为 false boolean free = false; // 满足条件 if (c == 0) { free = true; // 将当前持有资源的线程设置为(也就是当前的线程A) null setExclusiveOwnerThread(null); } // 将state设置为0 setState(c); // return true; return free; }
-
unparkSuccessor(h);
// node 为 哨兵节点 private void unparkSuccessor(Node node) { /* * If status is negative (i.e., possibly needing signal) try * to clear in anticipation of signalling. It is OK if this * fails or if status is changed by waiting thread. */ // ws 的值为 -1 int ws = node.waitStatus; // 满足条件 if (ws < 0) // 比较并设置等待状态 设置为 0 compareAndSetWaitStatus(node, ws, 0); /* * Thread to unpark is held in successor, which is normally * just the next node. But if cancelled or apparently null, * traverse backwards from tail to find the actual * non-cancelled successor. */ // s = 线程B Node s = node.next; // 第一个不满足 || 第二个不满足; 来到第二个if if (s == null || s.waitStatus > 0) { s = null; for (Node t = tail; t != null && t != node; t = t.prev) if (t.waitStatus <= 0) s = t; } // 线程B != null if (s != null) // 将线程B唤醒 LockSupport.unpark(s.thread); }
执行完上述以后 会再次来到下面的方法
// node为当前线程B
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
// p为B的前驱节点为 哨兵节点
final Node p = node.predecessor();
// 第一个满足 && 因为当前的state已经设置为0所以获取成功 ; 进入if
if (p == head && tryAcquire(arg)) {
// 设置头节点为线程B
// setHead(node) 见 step_B
setHead(node);
// 哨兵节点的next指向null
p.next = null; // help GC
failed = false;
// 至此 线程B抢占资源 原来的线程B成为新的哨兵节点
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
// 来到这里以后首先会来到这里 查看step_A
// 这里为false 直接进行第二次循环
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
A. parkAndCheckInterrupt()
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
// 因为当前B线程已经被唤醒了 所以返回false , 打断状态为 false
return Thread.interrupted();
}
B.setHead(Node node)
// node 为 线程B
private void setHead(Node node) {
// 头节点指向线程B
head = node;
// 将当前的线程B设置为null
node.thread = null;
// 线程B的prev指向null
node.prev = null;
}