|
JavaTM 2 Platform Standard Ed. 6 |
|||||||||
上一個類別 下一個類別 | 框架 無框架 | |||||||||
摘要: 巢狀 | 欄位 | 建構子 | 方法 | 詳細資訊: 欄位 | 建構子 | 方法 |
java.lang.Object java.util.concurrent.locks.AbstractOwnableSynchronizer java.util.concurrent.locks.AbstractQueuedSynchronizer
public abstract class AbstractQueuedSynchronizer
為實作依賴於先進先出 (FIFO) 等待佇列的阻塞鎖和相關同步器(信號量、事件,等等)提供一個框架。此類別的設計目標是成為依靠單個原子 int 值來表示狀態的大多數同步器的一個有用基礎。子類別必須定義更改此狀態的受保護方法,並定義哪種狀態對於此物件意味著被獲取或被釋放。假定這些條件之後,此類別中的其他方法就可以實作所有排隊和阻塞機制。子類別可以維護其他狀態欄位,但只是為了獲得同步而只追蹤使用 getState()
、setState(int)
和 compareAndSetState(int, int)
方法來操作以原子方式更新的 int 值。
應該將子類別定義為非公共內部說明器類別,可用它們來實作其封閉類別的同步屬性。類別 AbstractQueuedSynchronizer 沒有實作任何同步介面。而是定義了諸如 acquireInterruptibly(int)
之類別的一些方法,在適當的時候可以通過具體的鎖和相關同步器來調用它們,以實作其公共方法。
此類別支持預設的獨佔 網要和共享 網要之一,或者二者都支持。處於獨佔網要下時,其他執行緒試圖獲取該鎖將無法取得成功。在共享網要下,多個執行緒獲取某個鎖可能(但不是一定)會獲得成功。此類別並不“瞭解”這些不同,除了機械地意識到當在共享網要下成功獲取某一鎖時,下一個等待執行緒(如果存在)也必須確定自己是否可以成功獲取該鎖。處於不同網要下的等待執行緒可以共享相同的 FIFO 佇列。通常,實作子類別只支持其中一種網要,但兩種網要都可以在(例如)ReadWriteLock
中發揮作用。只支持獨佔網要或者只支持共享網要的子類別不必定義支持未使用網要的方法。
此類別通過支持獨佔網要的子類別定義了一個巢狀的 AbstractQueuedSynchronizer.ConditionObject
類別,可以將這個類別用作 Condition
實作。isHeldExclusively()
方法將報告同步對於當前執行緒是否是獨佔的;使用當前 getState()
值調用 release(int)
方法則可以完全釋放此物件;如果給定保存的狀態值,那麼 acquire(int)
方法可以將此物件最終恢復為它以前獲取的狀態。沒有別的 AbstractQueuedSynchronizer 方法創建這樣的條件,因此,如果無法滿足此約束,則不要使用它。AbstractQueuedSynchronizer.ConditionObject
的行為當然取決於其同步器實作的語義。
此類別為內部佇列提供了檢查、檢測和監視方法,還為 condition 物件提供了類似方法。可以根據需要使用用於其同步機制的 AbstractQueuedSynchronizer 將這些方法導出到類別中。
此類別的序列化只存儲維護狀態的基礎原子整數,因此已序列化的物件擁有空的執行緒佇列。需要可序列化的典型子類別將定義一個 readObject 方法,該方法在反序列化時將此物件恢復到某個已知初始狀態。
為了將此類別用作同步器的基礎,需要適當地重新定義以下方法,這是通過使用 getState()
、setState(int)
和/或 compareAndSetState(int, int)
方法來檢查和/或修改同步狀態來實作的:
UnsupportedOperationException
。這些方法的實作在內部必須是執行緒安全的,通常應該很短並且不被阻塞。定義這些方法是使用此類別的唯一 受支持的方式。其他所有方法都被宣告為 final,因為它們無法是各不相同的。
您也可以尋找從 AbstractOwnableSynchronizer
繼承的方法,用於追蹤擁有獨佔同步器的執行緒。鼓勵使用這些方法,這允許監控和診斷工具來說明使用者確定哪個執行緒保持鎖。
即使此類別基於內部的某個 FIFO 佇列,它也無法強行實施 FIFO 獲取策略。獨佔同步的核心採用以下形式:
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 來禁用闖入。特別是 getFirstQueuedThread()
沒有返回當前執行緒的時候,嚴格的 FIFO 鎖定可以定義 tryAcquire 立即返回 false。只有 hasQueuedThreads()
返回 true 並且 getFirstQueuedThread 不是當前執行緒時,更好的非嚴格公平的版本才可能會立即返回 false;如果 getFirstQueuedThread 不為 null 並且不是當前執行緒,則產生的結果相同。出現進一步的變體也是有可能的。
對於預設闖入(也稱為 greedy、renouncement 和 convoy-avoidance)策略,吞吐量和可伸縮性通常是最高的。儘管無法保證這是公平的或是無偏向的,但允許更早加入佇列的執行緒先於更遲加入佇列的執行緒再次爭用資源,並且相對於傳入的執行緒,每個參與再爭用的執行緒都有平等的成功機會。此外,儘管從一般意義上說,獲取並非“自旋”,它們可以在阻塞之前對用其他計算所使用的 tryAcquire 執行多次調用。在只保持獨佔同步時,這為自旋提供了最大的好處,但不是這種情況時,也不會帶來最大的負擔。如果需要這樣做,那麼可以使用“快速路徑”檢查來先行調用 acquire 方法,以這種方式擴充這一點,如果可能不需要爭用同步器,則只能通過預先檢查 hasContended()
和/或 hasQueuedThreads()
來確認這一點。
通過特殊化其同步器的使用範圍,此類別為部分同步化提供了一個有效且可伸縮的基礎,同步器可以依賴於 int 型的 state、acquire 和 release 參數,以及一個內部的 FIFO 等待佇列。這些還不夠的時候,可以使用 atomic
類別、自己的定制 Queue
類別和 LockSupport
阻塞支持,從更低層級別建構同步器。
以下是一個非再進入的互斥鎖類別,它使用值 0 表示未鎖定狀態,使用 1 表示鎖定狀態。當非重入鎖定不嚴格地需要當前擁有者執行緒的記錄時,此類別使得使用監視器更加方便。它還支持一些條件並公開了一個檢測方法:
class Mutex implements Lock, java.io.Serializable { // Our internal helper class private static class Sync extends AbstractQueuedSynchronizer { // Report whether in locked state protected boolean isHeldExclusively() { return getState() == 1; } // Acquire 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; } // Release 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; } // Provide a Condition Condition newCondition() { return new ConditionObject(); } // Deserialize 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); } }
巢狀類別摘要 | |
---|---|
class |
AbstractQueuedSynchronizer.ConditionObject
AbstractQueuedSynchronizer 的 Condition 實作是 Lock 實作的基礎。 |
建構子摘要 | |
---|---|
protected |
AbstractQueuedSynchronizer()
創建具有初始同步狀態 0 的新 AbstractQueuedSynchronizer 實例。 |
方法摘要 | |
---|---|
void |
acquire(int arg)
以獨佔網要獲取物件,忽略中斷。 |
void |
acquireInterruptibly(int arg)
以獨佔網要獲取物件,如果被中斷則中止。 |
void |
acquireShared(int arg)
以共享網要獲取物件,忽略中斷。 |
void |
acquireSharedInterruptibly(int arg)
以共享網要獲取物件,如果被中斷則中止。 |
protected boolean |
compareAndSetState(int expect,
int update)
如果當前狀態值等於預期值,則以原子方式將同步狀態設置為給定的更新值。 |
Collection<Thread> |
getExclusiveQueuedThreads()
返回包含可能正以獨佔網要等待獲取的執行緒 collection。 |
Thread |
getFirstQueuedThread()
返回佇列中第一個(等待時間最長的)執行緒,如果目前沒有將任何執行緒加入佇列,則返回 null .
在此實作中,該操作是以固定時間返回的,但是,如果其他執行緒目前正在共時修改該佇列,則可能出現循環爭用。 |
Collection<Thread> |
getQueuedThreads()
返回包含可能正在等待獲取的執行緒 collection。 |
int |
getQueueLength()
返回等待獲取的執行緒數估計值。 |
Collection<Thread> |
getSharedQueuedThreads()
返回包含可能正以共享網要等待獲取的執行緒 collection。 |
protected int |
getState()
返回同步狀態的當前值。 |
Collection<Thread> |
getWaitingThreads(AbstractQueuedSynchronizer.ConditionObject condition)
返回一個 collection,其中包含可能正在等待與此同步器有關的給定條件的那些執行緒。 |
int |
getWaitQueueLength(AbstractQueuedSynchronizer.ConditionObject condition)
返回正在等待與此同步器有關的給定條件的執行緒數估計值。 |
boolean |
hasContended()
查詢是否其他執行緒也曾爭著獲取此同步器;也就是說,是否某個 acquire 方法已經阻塞。 |
boolean |
hasQueuedThreads()
查詢是否有正在等待獲取的任何執行緒。 |
boolean |
hasWaiters(AbstractQueuedSynchronizer.ConditionObject condition)
查詢是否有執行緒正在等待給定的、與此同步器相關的條件。 |
protected boolean |
isHeldExclusively()
如果對於當前(正調用的)執行緒,同步是以獨佔方式進行的,則返回 true 。 |
boolean |
isQueued(Thread thread)
如果給定執行緒的當前已加入佇列,則返回 true。 |
boolean |
owns(AbstractQueuedSynchronizer.ConditionObject condition)
查詢給定的 ConditionObject 是否使用了此同步器作為其鎖。 |
boolean |
release(int arg)
以獨佔網要釋放物件。 |
boolean |
releaseShared(int arg)
以共享網要釋放物件。 |
protected void |
setState(int newState)
設置同步狀態的值。 |
String |
toString()
返回標識此同步器及其狀態的字元串。 |
protected boolean |
tryAcquire(int arg)
試圖在獨佔網要下獲取物件狀態。 |
boolean |
tryAcquireNanos(int arg,
long nanosTimeout)
試圖以獨佔網要獲取物件,如果被中斷則中止,如果到了給定逾時時間,則會失敗。 |
protected int |
tryAcquireShared(int arg)
試圖在共享網要下獲取物件狀態。 |
boolean |
tryAcquireSharedNanos(int arg,
long nanosTimeout)
試圖以共享網要獲取物件,如果被中斷則中止,如果到了給定逾時時間,則會失敗。 |
protected boolean |
tryRelease(int arg)
試圖設置狀態來反映獨佔網要下的一個釋放。 |
protected boolean |
tryReleaseShared(int arg)
試圖設置狀態來反映共享網要下的一個釋放。 |
從類別 java.util.concurrent.locks.AbstractOwnableSynchronizer 繼承的方法 |
---|
getExclusiveOwnerThread, setExclusiveOwnerThread |
從類別 java.lang.Object 繼承的方法 |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
建構子詳細資訊 |
---|
protected AbstractQueuedSynchronizer()
方法詳細資訊 |
---|
protected final int getState()
protected final void setState(int newState)
newState
- 新的狀態值protected final boolean compareAndSetState(int expect, int update)
expect
- 預期值update
- 新值
protected boolean tryAcquire(int arg)
此方法總是由執行 acquire 的執行緒來調用。如果此方法報告失敗,則 acquire 方法可以將執行緒加入佇列(如果還沒有將它加入佇列),直到獲得其他某個執行緒釋放了該執行緒的信號。可以用此方法來實作 Lock.tryLock()
方法。
預設實作將拋出 UnsupportedOperationException
。
arg
- acquire 參數。該值總是傳遞給 acquire 方法的那個值,或者是因某個條件等待而保存在條目上的值。該值是不間斷的,並且可以表示任何內容。
true
。在成功的時候,此物件已經被獲取。
IllegalMonitorStateException
- 如果正在進行的獲取操作將在非法狀態下放置此同步器。必須以一致的方式拋出此異常,以便同步正確運行。
UnsupportedOperationException
- 如果不支持獨佔網要protected boolean tryRelease(int arg)
此方法總是由正在執行釋放的執行緒調用。
預設實作將拋出 UnsupportedOperationException
。
arg
- release 參數。該值總是傳遞給 release 方法的那個值,或者是因某個條件等待而保存在條目上的當前狀態值。該值是不間斷的,並且可以表示任何內容。
true
;否則返回 false
。
IllegalMonitorStateException
- 如果正在進行的釋放操作將在非法狀態下放置此同步器。必須以一致的方式拋出此異常,以便同步正確運行。
UnsupportedOperationException
- 如果不支持獨佔網要protected int tryAcquireShared(int arg)
此方法總是由執行 acquire 執行緒來調用。如果此方法報告失敗,則 acquire 方法可以將執行緒加入佇列(如果還沒有將它加入佇列),直到獲得其他某個執行緒釋放了該執行緒的信號。
預設實作將拋出 UnsupportedOperationException
。
arg
- acquire 參數。該值總是傳遞給 acquire 方法的那個值,或者是因某個條件等待而保存在條目上的值。該值是不間斷的,並且可以表示任何內容。
IllegalMonitorStateException
- 如果正在進行的獲取操作將在非法狀態下放置此同步器。必須以一致的方式拋出此異常,以便同步正確運行。
UnsupportedOperationException
- 如果不支持共享網要protected boolean tryReleaseShared(int arg)
此方法總是由正在執行釋放的執行緒調用。
預設實作將拋出 UnsupportedOperationException
。
arg
- release 參數。該值總是傳遞給 release 方法的那個值,或者是因某個條件等待而保存在條目上的當前狀態值。該值是不間斷的,並且可以表示任何內容。
true
;否則返回 false
IllegalMonitorStateException
- 如果正在進行的釋放操作將在非法狀態下放置此同步器。必須以一致的方式拋出此異常,以便同步正確運行
UnsupportedOperationException
- 如果不支持共享網要protected boolean isHeldExclusively()
true
。此方法是在每次調用非等待 AbstractQueuedSynchronizer.ConditionObject
方法時調用的。(等待方法則調用 release(int)
。)
預設實作將拋出 UnsupportedOperationException
。此方法只是 AbstractQueuedSynchronizer.ConditionObject
方法內進行內部調用,因此,如果不使用條件,則不需要定義它。
true
;其他情況則返回 false
UnsupportedOperationException
- 如果不支持這些條件public final void acquire(int arg)
tryAcquire(int)
來實作此方法,並在成功時返回。否則在成功之前,一直調用 tryAcquire(int)
將執行緒加入佇列,執行緒可能重複被阻塞或不被阻塞。可以使用此方法來實作 Lock.lock()
方法。
arg
- acquire 參數。此值被傳送給 tryAcquire(int)
,但它是不間斷的,並且可以表示任何內容。public final void acquireInterruptibly(int arg) throws InterruptedException
tryAcquire(int)
來實作此方法,並在成功時返回。否則在成功之前,或者執行緒被中斷之前,一直調用 tryAcquire(int)
將執行緒加入佇列,執行緒可能重複被阻塞或不被阻塞。可以使用此方法來實作 Lock.lockInterruptibly()
方法。
arg
- acquire 參數。此值被傳送給 tryAcquire(int)
,但它是不間斷的,並且可以表示任何內容。
InterruptedException
- 如果當前執行緒被中斷public final boolean tryAcquireNanos(int arg, long nanosTimeout) throws InterruptedException
tryAcquire(int)
來實作此方法,並在成功時返回。否則,在成功之前、執行緒被中斷之前或者到達逾時時間之前,一直調用 tryAcquire(int)
將執行緒加入佇列,執行緒可能重複被阻塞或不被阻塞。可以用此方法來實作 Lock.tryLock(long, TimeUnit)
方法。
arg
- acquire 參數。此值被傳送給 tryAcquire(int)
,但它是不間斷的,並且可以表示任何內容。nanosTimeout
- 等待的最長時間,以毫微秒為單位
true
,如果逾時,則返回 false
InterruptedException
- 如果當前執行緒被中斷public final boolean release(int arg)
tryRelease(int)
返回 true,則通過消除一個或多個執行緒的阻塞來實作此方法。可以使用此方法來實作 Lock.unlock()
方法
arg
- release 參數。此值被傳送給 tryRelease(int)
,但它是不間斷的,並且可以表示任何內容。
tryRelease(int)
返回的值public final void acquireShared(int arg)
tryAcquireShared(int)
來實作此方法,並在成功時返回。否則在成功之前,一直調用 tryAcquireShared(int)
將執行緒加入佇列,執行緒可能重複被阻塞或不被阻塞。
arg
- acquire 參數。此值被傳送給 tryAcquireShared(int)
,但它是不間斷的,並且可以表示任何內容。public final void acquireSharedInterruptibly(int arg) throws InterruptedException
tryAcquireShared(int)
來實作此方法,並在成功時返回。否則在成功或執行緒被中斷之前,一直調用 tryAcquireShared(int)
將執行緒加入佇列,執行緒可能重複被阻塞或不被阻塞。
arg
- acquire 參數。此值被傳送給 tryAcquireShared(int)
,但它是不間斷的,並且可以表示任何內容。
InterruptedException
- 如果當前執行緒被中斷public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout) throws InterruptedException
tryAcquireShared(int)
來實作此方法,並在成功時返回。否則在成功之前、執行緒被中斷之前或者到達逾時時間之前,一直調用 tryAcquireShared(int)
將執行緒加入佇列,執行緒可能重複被阻塞或不被阻塞。
arg
- acquire 參數。此值被傳送給 tryAcquireShared(int)
,但它是不間斷的,並且可以表示任何內容。nanosTimeout
- 等待的最長時間,以毫微秒為單位
true
,如果逾時,則返回 false
InterruptedException
- 如果當前執行緒被中斷public final boolean releaseShared(int arg)
tryReleaseShared(int)
返回 true,則通過消除一個或多個執行緒的阻塞來實作該方法。
arg
- release 參數。此值被傳送給 tryReleaseShared(int)
,但它是不間斷的,並且可以表示任何內容。
tryReleaseShared(int)
中返回的值public final boolean hasQueuedThreads()
true
並不能保證其他任何執行緒都將獲取物件。
在此實作中,該操作是以固定時間返回的。
true
。public final boolean hasContended()
在此實作中,該操作是以固定時間返回的。
true
public final Thread getFirstQueuedThread()
null
.
在此實作中,該操作是以固定時間返回的,但是,如果其他執行緒目前正在共時修改該佇列,則可能出現循環爭用。
null
public final boolean isQueued(Thread thread)
該實作將遍歷佇列,以確定給定執行緒是否存在。
thread
- 執行緒
true
NullPointerException
- 如果 thread 為 nullpublic final int getQueueLength()
public final Collection<Thread> getQueuedThreads()
public final Collection<Thread> getExclusiveQueuedThreads()
getQueuedThreads()
相同的屬性,除了它只返回那些因獨佔獲取而等待的執行緒。
public final Collection<Thread> getSharedQueuedThreads()
getQueuedThreads()
相同的屬性,除了它只返回那些因共享獲取而等待的執行緒。
public String toString()
"State ="
,後面是 getState()
的當前值,再後面是 "nonempty"
或 "empty"
,這取決於佇列是否為空。
Object
中的 toString
public final boolean owns(AbstractQueuedSynchronizer.ConditionObject condition)
condition
- 條件
NullPointerException
- 如果 condition 為 nullpublic final boolean hasWaiters(AbstractQueuedSynchronizer.ConditionObject condition)
condition
- 條件
IllegalMonitorStateException
- 如果不進行獨佔同步
IllegalArgumentException
- 如果給定的 condition 與此同步器無關
NullPointerException
- 如果 condition 為 nullpublic final int getWaitQueueLength(AbstractQueuedSynchronizer.ConditionObject condition)
condition
- 條件
IllegalMonitorStateException
- 如果不進行獨佔同步
IllegalArgumentException
- 如果給定的 condition 與此同步器無關
NullPointerException
- 如果 condition 為 nullpublic final Collection<Thread> getWaitingThreads(AbstractQueuedSynchronizer.ConditionObject condition)
condition
- 條件
IllegalMonitorStateException
- 如果不進行獨佔同步
IllegalArgumentException
- 如果給定的 condition 與此同步器無關
NullPointerException
- 如果 condition 為 null
|
JavaTM 2 Platform Standard Ed. 6 |
|||||||||
上一個類別 下一個類別 | 框架 無框架 | |||||||||
摘要: 巢狀 | 欄位 | 建構子 | 方法 | 詳細資訊: 欄位 | 建構子 | 方法 |
版權所有 2008 Sun Microsystems, Inc. 保留所有權利。請遵守GNU General Public License, version 2 only。