AbstractQueuedSynchronizer源碼分析(一)
1、父類:AbstractOwnableSynchronizer
在AbstractOwnableSynchronizer中只有一個屬性和對其的get()和set()方法。
exclusiveOwnerThread:這個屬性表明在獨佔模式下,擁有鎖的線程。AOS和子類AQS並不會使用這個屬性,而其子類可以在通過維護該屬性來控制線程訪問控制權。
public abstract class AbstractOwnableSynchronizer
implements java.io.Serializable {
private static final long serialVersionUID = 3737899427754241961L;
/** 空構造函數供子類使用。 */
protected AbstractOwnableSynchronizer() { }
/** 獨佔模式,擁有同步狀態的線程 */
private transient Thread exclusiveOwnerThread;
protected final void setExclusiveOwnerThread(Thread thread) {
exclusiveOwnerThread = thread;
}
protected final Thread getExclusiveOwnerThread() {
return exclusiveOwnerThread;
}
}
2、AbstractQueuedSynchronizer的靜態內部類Node
Node持有一個線程,並在表示該線程在同步器等待隊列中的狀態。直至其線程獲得了鎖,就會釋放這個Node節點。
Node屬性介紹
字段名稱 | 類型 | 默認值 | 作用 |
---|---|---|---|
SHARED | Node | new Node() | 標識節點以共享模式等待 |
EXCLUSIVE | Node | null | 標識節點以獨佔模式等待 |
CANCELLED | int | 1 | 標識線程已經被取消 |
SIGNAL | int | -1 | 標識當前節點的後繼節點的線程需要取消阻塞 |
CONDITION | int | -2 | 標識線程由於阻塞而處於等待狀態 |
PROPAGATE | int | -3 | 標識處於共享狀態下,下一次的acquire需要無條件地傳播 |
waitStatus | int | 0 | 標識處於初始狀態 |
prev | Node | null | 當前節點的前驅節點 |
next | Node | null | 當前節點的後繼節點 |
Node方法介紹
方法名 | 返回值 | 作用 |
---|---|---|
isShared() | boolean | 判斷該節點是否共享模式 |
predecessor() | Node | 獲取當前節點的前驅節點 |
static final class Node {
/** 標識節點以共享模式等待 */
static final Node SHARED = new Node();
/** 標識節點以獨佔模式等待 */
static final Node EXCLUSIVE = null;
/** 標識線程已經被取消 */
static final int CANCELLED = 1;
/** 標識當前節點的後繼節點的線程需要取消阻塞 */
static final int SIGNAL = -1;
/** 標識線程由於阻塞而處於等待狀態 */
static final int CONDITION = -2;
/** 標識處於共享狀態下,下一次的acquire需要無條件地傳播 */
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;
}
/** 獲取當前節點的前驅節點 */
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(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;
}
}
3、AbstractQueuedSynchronizer的基本數據結構
- AQS的基本數據結構以Node節點組成的等待隊列,可以理解爲“等待鎖的線程隊列”。
- 每個Node節點都持有一個“waitStatus”字段,用於標記線程當前的行爲。
- head節點的下一個節點會嘗試acquire,因爲head節點是一個dummy節點,不持有線程。
- 入隊操作是直接將節點加入隊列尾部。
- 線程獲取鎖後,Node節點釋放線程,並設置爲head頭結點。
下面圖示表示了AQS的數據結構
4、AbstractQueuedSynchronizer的public方法初識
public修飾的方法是提供給同步工具類使用的,如ReentrantLock、ReentrantReadWriteLock等同步工具使用的。
方法 | 返回值 | 作用 |
---|---|---|
acquire(int arg) | void | 不響應中斷的獲取獨佔鎖 |
acquireInterruptibly(int arg) | void | 響應中斷的獲取獨佔鎖 |
tryAcquireNanos(int arg, long nanosTimeout) | boolean | //TODO |
release(int arg) | boolean | 釋放獨佔鎖 |
acquireShared(int arg) | void | 不響應中斷的獲取共享鎖 |
acquireSharedInterruptibly(int arg) | void | 響應中斷的獲取共享鎖 |
tryAcquireSharedNanos(int arg, long nanosTimeout) | boolean | //TODO |
releaseShared(int arg) | boolean | 釋放共享鎖 |
上面是對後面的內容進行鋪墊,後續章節主要介紹鎖是如何對同步狀態進行管理。以上這個幾個方法是獲取同步狀態和釋放同步狀態的核心方法。會逐一對其邏輯進行詳細剖析。