AbstractQueuedSynchronizer解讀

  • public abstract class AbstractQueuedSynchronizer
    extends AbstractOwnableSynchronizer
    implements Serializable
            提供一個框架,用於實現依賴先進先出(FIFO)等待隊列的阻塞鎖和相關同步器(信號量,事件等)。 該類被設計爲大多數類型的同步器的有用依據,這些同步器依賴於單個原子 int值來表示狀態。 子類必須定義改變此狀態的受保護方法,以及根據該對象被獲取或釋放來定義該狀態的含義。 考慮到這些,這個類中的其餘方法執行全部排隊和阻塞機制。 子類能夠保持其餘狀態字段,但只以原子方式更新 int使用方法操縱值 getState()setState(int)compareAndSetState(int, int)被跟蹤相對於同步。

            子類應定義爲非公共內部助手類,用於實現其封閉類的同步屬性。 AbstractQueuedSynchronizer類不實現任何同步接口。 相反,它定義了一些方法,如acquireInterruptibly(int) ,能夠恰當地經過調用具體的鎖和相關同步器來實現其公共方法。api

    此類支持默認獨佔模式和共享模式。 當以獨佔模式獲取時,嘗試經過其餘線程獲取不能成功。 多線程獲取的共享模式可能(但不須要)成功。 除了在機械意義上,這個類不理解這些差別,當共享模式獲取成功時,下一個等待線程(若是存在)也必須肯定它是否也能夠獲取。 在不一樣模式下等待的線程共享相同的FIFO隊列。 一般,實現子類只支持這些模式之一,可是二者均可以在ReadWriteLock發揮做用 。 僅支持獨佔或僅共享模式的子類不須要定義支持未使用模式的方法。安全

    這個類定義的嵌套AbstractQueuedSynchronizer.ConditionObject可用於做爲一類Condition由子類支持獨佔模式用於該方法的實施isHeldExclusively()報告是否同步排他相對於保持在當前線程,方法release(int)與當前調用getState()值徹底釋放此目的,和acquire(int) ,給定此保存的狀態值,最終將此對象恢復到其先前獲取的狀態。 AbstractQueuedSynchronizer方法將建立此類條件,所以若是不能知足此約束,請勿使用該約束。 AbstractQueuedSynchronizer.ConditionObject的行爲固然取決於其同步器實現的語義。數據結構

    該類爲內部隊列提供檢查,檢測和監控方法,以及條件對象的相似方法。 這些能夠根據須要導出到類中,使用AbstractQueuedSynchronizer進行同步機制。多線程

    此類的序列化僅存儲底層原子整數維持狀態,所以反序列化對象具備空線程隊列。 須要可序列化的典型子類將定義一個readObject方法,能夠將其恢復爲readObject時的已知初始狀態。框架

    用法

    使用這個類用做同步的基礎上,從新定義如下方法,如適用,經過檢查和/或修改使用所述同步狀態getState()setState(int)和/或compareAndSetState(int, int)ide

    每一個這些方法默認拋出 UnsupportedOperationException 。 這些方法的實現必須是線程安全的,一般應該是短的而不是阻止的。 定義這些方法是 惟一支持使用此類的方法。 全部其餘方法都被聲明爲 final ,由於它們不能獨立變化。

    您還能夠找到來自繼承的方法AbstractOwnableSynchronizer有用跟蹤線程擁有獨家同步的。 咱們鼓勵您使用它們 - 這樣可使監控和診斷工具幫助用戶肯定哪些線程持有鎖定。工具

    即便這個類基於內部FIFO隊列,它也不會自動執行FIFO採集策略。 排他同步的核心形式以下:ui

    Acquire:
         while (!tryAcquire(arg)) {
            enqueue thread if it is not already queued;
            possibly block current thread;
         }
    
     Release:
         if (tryRelease(arg))
            unblock the first queued thread;
    (共享模式相似,但可能包含級聯信號。)

    由於在採集檢查入隊以前調用,因此新獲取的線程可能闖入其餘被阻塞和排隊的。 可是,若是須要,您能夠經過內部調用一個或多個檢查方法來定義tryAcquire和/或tryAcquireShared來禁用駁船,從而提供一個合理的 FIFO採購訂單。 特別地,最公平同步器能夠定義tryAcquire返回false若是hasQueuedPredecessors() (具體地設計成由公平同步器中使用的方法)返回true 。 其餘變化是可能的。

    吞吐量和可擴展性一般對於默認的駁船(也稱爲貪心放棄車隊避免 )戰略來講是最高的。 雖然這不能保證是公平的或無飢餓的,但較早排隊的線程在稍後排隊的線程以前被容許從新偵聽,而且每次從新提供對於傳入線程成功的機會。 此外,雖然獲取在一般意義上不「旋轉」,可是在阻止以前它們能夠執行多個tryAcquire tryAcquire與其餘計算的交互。 當獨佔同步只是簡單地持有時,這樣能夠提供旋轉的大部分好處,而沒有大部分負債。 若是須要,您能夠經過之前經過「快速路徑」檢查獲取方法的調用進行擴充,可能預先檢查hasContended()和/或hasQueuedThreads() ,以便只有在同步器可能不被競爭的狀況下才能進行。

    該類爲同步提供了一個高效和可擴展的基礎,部分緣由是能夠依靠int狀態,獲取和釋放參數以及內部FIFO等待隊列的同步器的使用範圍。 當這不足夠時,您可使用atomic類,您本身的自定義Queue類和LockSupport類阻止支持從較低級別構建同步器。

    用法示例

    這是一個不可重入互斥鎖類,它使用零值來表示解鎖狀態,一個表示鎖定狀態。 雖然不可重入鎖不嚴格要求記錄當前的全部者線程,可是這樣作不管如何使得使用更容易監視。 它還支持條件並公開其中一種儀器方法:

    class Mutex implements Lock, java.io.Serializable { // Our internal helper class private static class Sync extends AbstractQueuedSynchronizer { // Reports whether in locked state protected boolean isHeldExclusively() { return getState() == 1; } // Acquires the lock if state is zero public boolean tryAcquire(int acquires) { assert acquires == 1; // Otherwise unused if (compareAndSetState(0, 1)) { setExclusiveOwnerThread(Thread.currentThread()); return true; } return false; } // Releases the lock by setting state to zero protected boolean tryRelease(int releases) { assert releases == 1; // Otherwise unused if (getState() == 0) throw new IllegalMonitorStateException(); setExclusiveOwnerThread(null); setState(0); return true; } // Provides a Condition Condition newCondition() { return new ConditionObject(); } // Deserializes properly private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); setState(0); // reset to unlocked state } } // The sync object does all the hard work. We just forward to it. private final Sync sync = new Sync(); public void lock() { sync.acquire(1); } public boolean tryLock() { return sync.tryAcquire(1); } public void unlock() { sync.release(1); } public Condition newCondition() { return sync.newCondition(); } public boolean isLocked() { return sync.isHeldExclusively(); } public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); } public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1); } public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(timeout)); } }

    這是一個相似CountDownLatch的閂鎖類,只是它只須要一個signal才能觸發。 由於鎖存器是非排他的,它使用shared獲取和釋放方法。

    class BooleanLatch { private static class Sync extends AbstractQueuedSynchronizer { boolean isSignalled() { return getState() != 0; } protected int tryAcquireShared(int ignore) { return isSignalled() ? 1 : -1; } protected boolean tryReleaseShared(int ignore) { setState(1); return true; } } private final Sync sync = new Sync(); public boolean isSignalled() { return sync.isSignalled(); } public void signal() { sync.releaseShared(1); } public void await() throws InterruptedException { sync.acquireSharedInterruptibly(1); } }

    從如下版本開始:

    1.5

    另請參見:

    Serialized Form

    • 構造方法詳細信息

      • AbstractQueuedSynchronizer

        protected AbstractQueuedSynchronizer()
        建立一個初始同步狀態爲零的新的 AbstractQueuedSynchronizer實例。
    • 方法詳細信息

      • getState

        protected final int getState()
        返回同步狀態的當前值。 這個操做具備一個 volatile讀取的記憶語義。

        結果

        當前狀態值

      • setState

        protected final void setState(int newState)
        設置同步狀態的值。 這個操做有一個 volatile寫的內存語義。

        參數

        newState - 新的狀態值

      • compareAndSetState

        protected final boolean compareAndSetState(int expect,
                                                   int update)
        若是當前狀態值等於指望值,則將同步狀態原子地設置爲給定的更新值。 此操做具備 volatile讀寫的記憶語義。

        參數

        expect - 指望值

        update - 新的價值

        結果

        true若是成功。 False return表示實際值不等於預期值。

      • tryAcquire

        protected boolean tryAcquire(int arg)
        嘗試以獨佔模式獲取。 該方法應該查詢對象的狀態是否容許以獨佔模式獲取,若是是,則獲取它。

        該方法老是由執行獲取的線程調用。 若是此方法報告失敗,則獲取方法可能將線程排隊(若是還沒有排隊),直到被其餘線程釋放爲止。 這能夠用於實現方法Lock.tryLock()

        默認實現會拋出UnsupportedOperationException

        參數

        arg - 獲取的論據。 該值始終是傳遞給獲取方法的值,或者是進入條件等待時保存的值。 該值不然沒法解釋,能夠表明您喜歡的任何內容。

        結果

        true若是成功。 一旦成功,這個對象就被收購了。

        異常

        IllegalMonitorStateException - 若是獲取將該同步器置於非法狀態。 必須以一致的方式拋出此異常,以使同步正常工做。

        UnsupportedOperationException - 若是不支持獨佔模式

      • tryRelease

        protected boolean tryRelease(int arg)
        嘗試設置狀態以獨佔模式反映版本。

        該方法老是由執行釋放的線程調用。

        默認實現拋出UnsupportedOperationException

        參數

        arg - 釋放參數。 該值始終是傳遞給release方法的值,或者進入條件等待時的當前狀態值。 該值不然沒法解釋,能夠表明您喜歡的任何內容。

        結果

        true若是此對象如今處於徹底釋放狀態,那麼任何等待的線程均可能嘗試獲取; 和false其餘。

        異常

        IllegalMonitorStateException - 若是釋放將使此同步器處於非法狀態。 必須以一致的方式拋出此異常,以使同步正常工做。

        UnsupportedOperationException - 若是不支持獨佔模式

      • tryAcquireShared

        protected int tryAcquireShared(int arg)
        嘗試以共享模式獲取。 該方法應該查詢對象的狀態是否容許在共享模式下獲取該對象,若是是這樣,就能夠獲取它。

        該方法老是由執行獲取的線程調用。 若是此方法報告失敗,則獲取方法可能將線程排隊(若是還沒有排隊),直到被其餘線程釋放爲止。

        默認實現拋出UnsupportedOperationException

        參數

        arg - 獲取的論據。 該值始終是傳遞給獲取方法的值,或者是進入條件等待時保存的值。 該值不然沒法解釋,能夠表明您喜歡的任何內容。

        結果

        失敗的負值 若是在共享模式下獲取成功但沒有後續共享模式獲取能夠成功,則爲零; 而且若是以共享模式獲取成功而且隨後的共享模式獲取可能成功,則爲正值,在這種狀況下,後續等待線程必須檢查可用性。 (支持三種不一樣的返回值使得這種方法能夠在僅獲取有時只能徹底執行的上下文中使用。)成功後,該對象已被獲取。

        異常

        IllegalMonitorStateException - 若是獲取將該同步器置於非法狀態。 必須以一致的方式拋出此異常,以使同步正常工做。

        UnsupportedOperationException - 若是不支持共享模式

      • tryReleaseShared

        protected boolean tryReleaseShared(int arg)
        嘗試將狀態設置爲以共享模式反映發佈。

        該方法老是由執行釋放的線程調用。

        默認實現會拋出UnsupportedOperationException

        參數

        arg - 釋放參數。 該值始終是傳遞給release方法的值,或者進入條件等待時的當前狀態值。 該值不然沒法解釋,能夠表明您喜歡的任何內容。

        結果

        true若是這種共享模式的釋放可能容許等待獲取(共享或排他)成功; false false

        異常

        IllegalMonitorStateException - 若是釋放將使此同步器處於非法狀態。 必須以一致的方式拋出此異常,以使同步正常工做。

        UnsupportedOperationException - 若是不支持共享模式

      • acquire

        public final void acquire(int arg)
        以獨佔模式獲取,忽略中斷。 經過調用至少一次 tryAcquire(int)實現,成功返回。 不然線程排隊,可能會重複阻塞和解除阻塞,直到成功才調用 tryAcquire(int) 。 該方法可用於實現方法 Lock.lock()

        參數

        arg - 收購論據。 該值傳達到tryAcquire(int),不然將沒法解釋,能夠表明您喜歡的任何內容。

      • acquireInterruptibly

        public final void acquireInterruptibly(int arg)
                                        throws InterruptedException
        以獨佔方式得到,若是中斷,停止。 經過首先檢查中斷狀態,而後調用至少一次 tryAcquire(int) ,成功返回。 不然線程排隊,可能會重複阻塞和解除阻塞,調用 tryAcquire(int)直到成功或線程中斷。 該方法能夠用於實現方法 Lock.lockInterruptibly()

        參數

        arg - 獲取的論據。 這個值傳達給tryAcquire(int)可是沒有被解釋,能夠表明你喜歡的任何東西。

        異常

        InterruptedException - 當前線程是否中斷

      • tryAcquireNanos

        public final boolean tryAcquireNanos(int arg,
                                             long nanosTimeout)
                                      throws InterruptedException
        嘗試以獨佔模式獲取,若是中斷則停止,若是給定的超時時間失敗。 首先檢查中斷狀態,而後調用至少一次 tryAcquire(int) ,成功返回。 不然,線程排隊,可能會重複阻塞和解除阻塞,調用 tryAcquire(int)直到成功或線程中斷或超時。 該方法可用於實現方法 Lock.tryLock(long, TimeUnit)

        參數

        arg - 獲取的論據。 該值傳達到tryAcquire(int) ,不然沒法解釋,能夠表明您喜歡的任何內容。

        nanosTimeout - 要等待的最大納秒數

        結果

        true若是得到; false若是超時

        異常

        InterruptedException - 當前線程是否中斷

      • release

        public final boolean release(int arg)
        以專屬模式發佈。 若是 tryRelease(int)返回true,則經過解除阻塞一個或多個線程 實現。 該方法能夠用於實現方法 Lock.unlock()

        參數

        arg - 釋放參數。 這個值被傳達到tryRelease(int)可是沒有被解釋,能夠表明你喜歡的任何東西。

        結果

        tryRelease(int)返回的值

      • acquireShared

        public final void acquireShared(int arg)
        以共享模式獲取,忽略中斷。 經過首次調用至少一次 執行 tryAcquireShared(int),成功返回。 不然線程排隊,可能會重複阻塞和解除阻塞,直到成功調用 tryAcquireShared(int)

        參數

        arg - 獲取的論據。 該值傳達給tryAcquireShared(int),不然將被解釋,能夠表明您喜歡的任何內容。

      • acquireSharedInterruptibly

        public final void acquireSharedInterruptibly(int arg)
                                              throws InterruptedException
        以共享方式獲取,若是中斷,停止。 首先檢查中斷狀態,而後調用至少一次 tryAcquireShared(int) ,成功返回。 不然線程排隊,可能會重複阻塞和解除阻塞,調用 tryAcquireShared(int)直到成功或線程中斷。

        參數

        arg - 獲取的論據。 該值傳達給tryAcquireShared(int) ,不然沒法解釋,能夠表明您喜歡的任何內容。

        異常

        InterruptedException - 當前線程是否中斷

      • tryAcquireSharedNanos

        public final boolean tryAcquireSharedNanos(int arg,
                                                   long nanosTimeout)
                                            throws InterruptedException
        嘗試以共享模式獲取,若是中斷則停止,若是給定的時間超過,則失敗。 經過首先檢查中斷狀態,而後調用至少一次 tryAcquireShared(int) ,成功返回。 不然,線程排隊,可能會重複阻塞和解除阻塞,調用 tryAcquireShared(int)直到成功或線程中斷或超時。

        參數

        arg - 收購論據。 該值傳達到tryAcquireShared(int) ,不然沒法解釋,能夠表明您喜歡的任何內容。

        nanosTimeout - 等待的最大納秒數

        結果

        true若是得到; false若是超時

        異常

        InterruptedException - 若是當前線程中斷

      • releaseShared

        public final boolean releaseShared(int arg)
        以共享模式發佈。 若是 tryReleaseShared(int)返回true,則經過解除阻塞一個或多個線程 實現。

        參數

        arg - 釋放參數。 該值傳達給tryReleaseShared(int) ,不然沒法解釋,能夠表明您喜歡的任何內容。

        結果

        tryReleaseShared(int)返回的值

      • hasQueuedThreads

        public final boolean hasQueuedThreads()
        查詢任何線程是否等待獲取。 請注意,因爲中斷和超時可能會隨時發生 truetrue返回不能保證任何其餘線程將得到。

        在這個實現中,這個操做返回恆定的時間。

        結果

        true若是可能有其餘線程等待獲取

      • hasContended

        public final boolean hasContended()
        查詢任何線程是否有爭取獲取此同步器; 那就是收購方法是否被阻止。

        在這個實現中,這個操做返回恆定的時間。

        結果

        true若是有爭議

      • getFirstQueuedThread

        public final Thread getFirstQueuedThread()
        返回隊列中第一個(等待時間最長的)線程,或 null若是沒有線程正在排隊。

        在這個實現中,這個操做一般在常量時間內返回,但若是其餘線程同時修改隊列,則能夠在爭用時迭代。

        結果

        在隊列中的第一個(等待時間最長的)螺紋,或 null若是沒有線程當前排隊

      • isQueued

        public final boolean isQueued(Thread thread)
        若是給定的線程當前排隊,則返回true。

        該實現遍歷隊列以肯定給定線程的存在。

        參數

        thread - 線程

        結果

        true若是給定的線程在隊列上

        異常

        NullPointerException - 若是線程爲空

      • hasQueuedPredecessors

        public final boolean hasQueuedPredecessors()
        查詢任何線程是否等待獲取比當前線程更長的時間。

        調用此方法等同於(但可能更有效):

        getFirstQueuedThread() != Thread.currentThread() && hasQueuedThreads()

        請注意,因爲中斷和超時可能會隨時發生true ,所以true返回不能保證其餘一些線程將在當前線程以前獲取。 一樣,因爲隊列爲空,這個方法已經返回false ,所以另外一個線程可能會贏得比賽排入隊列。

        該方法被設計爲由一個公平的同步器使用,以免barging 。 這樣一個同步器的tryAcquire(int)方法應該返回false ,而且它的tryAcquireShared(int)方法應該返回一個負值,若是這個方法返回true (除非這是一個可重入的獲取)。 例如, tryAcquire公平,可重入,獨佔模式同步器的方法可能以下所示:

        protected boolean tryAcquire(int arg) { if (isHeldExclusively()) { // A reentrant acquire; increment hold count return true; } else if (hasQueuedPredecessors()) { return false; } else { // try to acquire normally } }

        結果

        true若是當前線程以前有一個排隊的線程,若是當前線程在隊列的頭部或隊列爲空, false

        從如下版本開始:

        1.7

      • getQueueLength

        public final int getQueueLength()
        返回等待獲取的線程數的估計。 該值只是一個估計,由於線程數可能會在此方法遍歷內部數據結構時動態更改。 該方法設計用於監控系統狀態,不用於同步控制。

        結果

        估計等待獲取的線程數

      • getQueuedThreads

        public final Collection<Thread> getQueuedThreads()
        返回一個包含可能正在等待獲取的線程的集合。 由於在構建此結果時,實際的線程集可能會動態更改,因此返回的集合只是盡力而爲的估計。 返回的集合的元素沒有特定的順序。 該方法旨在便於構建提供更普遍監控設施的子類。

        結果

        線程的收集

      • getExclusiveQueuedThreads

        public final Collection<Thread> getExclusiveQueuedThreads()
        返回一個包含可能正在等待以獨佔模式獲取的線程的集合。 這具備相同的屬性, getQueuedThreads() ,除了它只返回那些等待的線程因爲獨家獲取。

        結果

        線程的收集

      • getSharedQueuedThreads

        public final Collection<Thread> getSharedQueuedThreads()
        返回包含可能正在等待在共享模式下獲取的線程的集合。 這具備相同的特性 getQueuedThreads() ,但它僅返回那些等待的線程因爲共享獲取。

        結果

        線程的收集

      • toString

        public String toString()
        返回一個標識此同步器的字符串及其狀態。 的狀態下,在括號中,它包括字符串 "State ="接着的當前值 getState() ,而且或者 "nonempty""empty"取決於隊列是否爲空。

        重寫:

        toString在類別 Object

        結果

        識別此同步器的字符串以及其狀態

      • hasWaiters

        public final boolean hasWaiters(AbstractQueuedSynchronizer.ConditionObject condition)
        查詢任何線程是否等待與此同步器相關聯的給定條件。 請注意,因爲超時和中斷可能隨時發生, true返回不能保證將來的 signal將喚醒任何線程。 該方法主要用於監視系統狀態。

        參數

        condition - 條件

        結果

        true若是有任何等待線程

        異常

        IllegalMonitorStateException - 若是不保留獨佔同步

        IllegalArgumentException - 若是給定的條件與此同步器無關

        NullPointerException - 若是條件爲空

      • getWaitQueueLength

        public final int getWaitQueueLength(AbstractQueuedSynchronizer.ConditionObject condition)
        返回等待與此同步器相關聯的給定條件的線程數量的估計。 請注意,因爲超時和中斷可能在任什麼時候間發生,估計僅做爲實際服務員人數的上限。 該方法設計用於監視系統狀態,不用於同步控制。

        參數

        condition - 條件

        結果

        估計等待線程數

        異常

        IllegalMonitorStateException - 若是不保留獨佔同步

        IllegalArgumentException - 若是給定的條件與該同步器沒有關聯

        NullPointerException - 若是條件爲空

相關文章
相關標籤/搜索