AbstractQueuedSynchronizer源碼分析(一):AbstractOwnableSynchronizer和Node

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的基本數據結構

  1. AQS的基本數據結構以Node節點組成的等待隊列,可以理解爲“等待鎖的線程隊列”。
  2. 每個Node節點都持有一個“waitStatus”字段,用於標記線程當前的行爲。
  3. head節點的下一個節點會嘗試acquire,因爲head節點是一個dummy節點,不持有線程。
  4. 入隊操作是直接將節點加入隊列尾部。
  5. 線程獲取鎖後,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 釋放共享鎖

上面是對後面的內容進行鋪墊,後續章節主要介紹鎖是如何對同步狀態進行管理。以上這個幾個方法是獲取同步狀態和釋放同步狀態的核心方法。會逐一對其邏輯進行詳細剖析。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章