- AQS是什麼呢??
我認爲AQS是一個同步的輔助工具,當出現對公共資源的競爭時,AQS維持了一個雙向隊列,用於存儲獲取資源的線程對象。
AQS封裝了許多基礎的方法,如等待超時,線程中斷處理等。下面的一張圖是對AQS主要功能的一個較好詮釋。
state代表的是公共資源,位於head的線程表示獲得資源所有權,隊列後面的線程處於阻塞狀態。
AQS 支持兩種模式下來的資源獲取,獨佔模式及共享模式,它是一個抽象類,只要我們繼承它並實現一些基礎方法如
tryAcquire(int args)等try開頭的模板方法,就能實現一個具有等待功能的資源同步器。我們熟悉的相關Lock的實現都是依靠於AQS來實現的。
AQS 的主要成員及方法。
先來看看AQS對於節點的封裝Node
static final class Node {
/** 標識該節點是否處於共享狀態的等待狀態 */
static final Node SHARED = new Node();
/** 標識該節點是否處於獨佔模式的等待狀態 */
static final Node EXCLUSIVE = null;
/** 取消狀態 幾個狀態中唯一一個大於1的 */
static final int CANCELLED = 1;
/** 等待被喚醒 */
static final int SIGNAL = -1;
/** 處於條件等待狀態中 */
static final int CONDITION = -2;
/**
* 用於共享模式下的傳播,至今不太明白有什麼作用
*
*/
static final int PROPAGATE = -3;
/**
* 節點狀態。必須用cas來修改期狀態
*
*/
volatile int waitStatus;
/**
* 前一個節點
*/
volatile Node prev;
/**
* 下一個節點
*/
volatile Node next;
/**
* 當前節點的持有線程
*/
volatile Thread thread;
/**
*
*/
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() {
}
Node(Thread thread, Node mode) {
this.nextWaiter = mode;
this.thread = thread;
}
Node(Thread thread, int waitStatus) {
this.waitStatus = waitStatus;
this.thread = thread;
}
}
接下來看看一個接口,該接口類似於Object的wait(),notify(),notifyAll()主要用於條件等待。
public interface Condition {
/**
* 同wait()方法,釋放鎖,阻塞。
*
*/
void await() throws InterruptedException;
/**
* 釋放鎖直到線程中斷
*
*/
void awaitUninterruptibly();
/**
*
* 阻塞指定時間後醒來,然後重新參與鎖的競爭(重新進入等待隊列,有可能還會重新阻塞)
*/
long awaitNanos(long nanosTimeout) throws InterruptedException;
/**
* 跟上一個方法沒什麼區別
*/
boolean await(long time, TimeUnit unit) throws InterruptedException;
/**
* 同一類
*/
boolean awaitUntil(Date deadline) throws InterruptedException;
/**
* 喚醒一個等待線程
*/
void signal();
/**
* 喚醒所有等待的線程,然後回重新參與競爭
*/
void signalAll();
}
這裏一點挺值得關注的,wait() 或者 await() 指定時間的時候,到了指定時間之後,其實並不會立即中斷,只是阻塞停止而已,
然後又繼續參與鎖的競爭。然後參與競爭的過程中有可能是進入了等待隊列,又會重新阻塞。
AQS中有一個內部類,ConditionObject,他實現了Condition 接口。
public class ConditionObject implements Condition, java.io.Serializable {
private static final long serialVersionUID = 1173984872572414699L;
private transient Node firstWaiter;
private transient Node lastWaiter;
public ConditionObject() { }
// Internal methods
/**
* 往條件等待隊列中添加一個等待節點
*/
private Node addConditionWaiter() {
Node t = lastWaiter;
// If lastWaiter is cancelled, clean out.
if (t != null && t.waitStatus != Node.CONDITION) {
unlinkCancelledWaiters();
t = lastWaiter;
}
Node node = new Node(Thread.currentThread(), Node.CONDITION);
if (t == null)
firstWaiter = node;
else
t.nextWaiter = node;
lastWaiter = node;
return node;
}
/**
* 喚醒首節點
*/
private void doSignal(Node first) {
do {
if ( (firstWaiter = first.nextWaiter) == null)
lastWaiter = null;
first.nextWaiter = null;
} while (!transferForSignal(first) &&
(first = firstWaiter) != null);
}
/**
* 喚醒所有等待節點
*
*/
private void doSignalAll(Node first) {
lastWaiter = firstWaiter = null;
do {
Node next = first.nextWaiter;
first.nextWaiter = null;
transferForSignal(first);
first = next;
} while (first != null);
}
/**
* 清除等待狀態的節點
*/
private void unlinkCancelledWaiters() {
Node t = firstWaiter;
Node trail = null;
while (t != null) {
Node next = t.nextWaiter;
if (t.waitStatus != Node.CONDITION) {
t.nextWaiter = null;
if (trail == null)
firstWaiter = next;
else
trail.nextWaiter = next;
if (next == null)
lastWaiter = trail;
}
else
trail = t;
t = next;
}
}
/**
* 實現Condition的方法
*/
public final void signal() {
// 條件等待僅在獨佔模式下課用
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignal(first);
}
/**
* 實現Condition 的方法
*/
public final void signalAll() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignalAll(first);
}
/**
* 實現Condition 的方法
*/
public final void awaitUninterruptibly() {
// 添加等待節點
Node node = addConditionWaiter();
// 釋放AQS 中的節點
long savedState = fullyRelease(node);
boolean interrupted = false;
while (!isOnSyncQueue(node)) {
// 阻塞
LockSupport.park(this);
// 響應中斷
if (Thread.interrupted())
interrupted = true;
}
// 被喚醒了 重新進去AQS 進行鎖競爭 並對中斷進行響應
if (acquireQueued(node, savedState) || interrupted)
selfInterrupt();
}
/*
*
*/
private int checkInterruptWhileWaiting(Node node) {
return Thread.interrupted() ?
(transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
0;
}
/**
* Throws InterruptedException, reinterrupts current thread, or
* does nothing, depending on mode.
*/
private void reportInterruptAfterWait(int interruptMode)
throws InterruptedException {
if (interruptMode == THROW_IE)
throw new InterruptedException();
else if (interruptMode == REINTERRUPT)
selfInterrupt();
}
/**
*
*/
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
long savedState = fullyRelease(node);
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
/**
*
*/
public final long awaitNanos(long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
long savedState = fullyRelease(node);
final long deadline = System.nanoTime() + nanosTimeout;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
if (nanosTimeout <= 0L) {
transferAfterCancelledWait(node);
break;
}
if (nanosTimeout >= spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
nanosTimeout = deadline - System.nanoTime();
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null)
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
return deadline - System.nanoTime();
}
/**
*
*/
public final boolean awaitUntil(Date deadline)
throws InterruptedException {
long abstime = deadline.getTime();
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
long savedState = fullyRelease(node);
boolean timedout = false;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
if (System.currentTimeMillis() > abstime) {
timedout = transferAfterCancelledWait(node);
break;
}
LockSupport.parkUntil(this, abstime);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null)
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
return !timedout;
}
/**
* 等待指定時間
*/
public final boolean await(long time, TimeUnit unit)
throws InterruptedException {
long nanosTimeout = unit.toNanos(time);
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
long savedState = fullyRelease(node);
final long deadline = System.nanoTime() + nanosTimeout;
boolean timedout = false;
int interruptMode = 0;
//如果再同步隊列你說明被喚醒了
while (!isOnSyncQueue(node)) {
if (nanosTimeout <= 0L) {
timedout = transferAfterCancelledWait(node);
break;
}
if (nanosTimeout >= spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
nanosTimeout = deadline - System.nanoTime();
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null)
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
return !timedout;
}
// support for instrumentation
/**
* Returns true if this condition was created by the given
* synchronization object.
*
* @return {@code true} if owned
*/
final boolean isOwnedBy(AbstractQueuedLongSynchronizer sync) {
return sync == AbstractQueuedLongSynchronizer.this;
}
/**
* 判斷是否有等待節點
*/
protected final boolean hasWaiters() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
if (w.waitStatus == Node.CONDITION)
return true;
}
return false;
}
/**
* 獲取等待隊列的長度
*/
protected final int getWaitQueueLength() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
int n = 0;
for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
if (w.waitStatus == Node.CONDITION)
++n;
}
return n;
}
/**
* 獲取所有等待線程
*/
protected final Collection<Thread> getWaitingThreads() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
ArrayList<Thread> list = new ArrayList<Thread>();
for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
if (w.waitStatus == Node.CONDITION) {
Thread t = w.thread;
if (t != null)
list.add(t);
}
}
return list;
}
}
接下來看看AQS一些關鍵的方法。
/**
* 獲取獨佔鎖
* tryAcquired(arg)爲模板方法,由子類實現
* addWaiter() 爲創建Node 節點 acquireQueued()阻塞獲取鎖
* selfInterrupt 爲 中斷處理
*/
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
/**
* 創建節點 並加入隊列尾部
*
*
*/
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// 如果沒併發,就直接加入尾部即可
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
//上面未能直接加入尾部,下面會進行循環加入隊列尾部直至成功
enq(node);
return 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;
}
}
}
}
/**
* 真正滴去獲取獨佔鎖
*
*
* @param node the node
* @param arg the acquire argument
* @return {@code true} if interrupted while waiting
*/
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
// 如果當前節點的前節點是頭節點且獲取鎖成功則成功
if (p == head && tryAcquire(arg)) {
// 設置當前節點爲頭節點
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
// 判斷是否需要阻塞 並且找到一個安全進行阻塞(有人喚醒自己就是安全的)
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
//失敗獲取了,就要去釋放節點
cancelAcquire(node);
}
}
/**
* 就是等待了,並返回是否中斷過
*
* @return {@code true} if interrupted
*/
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}