- java.lang.Object
-
- java.util.concurrent.Semaphore
-
- すべての
実装 されたインタフェース: Serializable
public class Semaphore extends Object implements Serializable
計数 セマフォです。概念的 に、セマフォはパーミットのセットを維持 します。各 acquire()
は、パーミットが利用 可能 になるまで必要 に応 じてブロックし、その後 パーミットを取得 します。各 release()
はパーミットを追加 し、場合 によってはブロックしている取得 側 を解放 します。 ただし、実際 のパーミット・オブジェクトは使用 されません。Semaphore
は単 に利用 可能 な個数 のカウントを保持 し、それに応 じた処理 を行 います。セマフォは、
物理 的 または論理 的 な一部 のリソースにアクセス可能 なスレッド数 を制限 するためによく使用 されます。 たとえば、次 のクラスでは、セマフォを使用 して項目 のプールへのアクセスを制御 します。class Pool { private static final int MAX_AVAILABLE = 100; private final Semaphore available = new Semaphore(MAX_AVAILABLE, true); public Object getItem() throws InterruptedException { available.acquire(); return getNextAvailableItem(); } public void putItem(Object x) { if (markAsUnused(x)) available.release(); } // Not a particularly efficient data structure; just for demo protected Object[] items = ... whatever kinds of items being managed protected boolean[] used = new boolean[MAX_AVAILABLE]; protected synchronized Object getNextAvailableItem() { for (int i = 0; i < MAX_AVAILABLE; ++i) { if (!used[i]) { used[i] = true; return items[i]; } } return null; // not reached } protected synchronized boolean markAsUnused(Object item) { for (int i = 0; i < MAX_AVAILABLE; ++i) { if (item == items[i]) { if (used[i]) { used[i] = false; return true; } else return false; } } return false; } }
項目 を取得 する前 に、各 スレッドはセマフォから、項目 が利用 可能 であることを保証 するパーミットを取得 する必要 があります。項目 の処理 が完了 するとスレッドはプールに戻 り、パーミットがセマフォに返 され、ほかのスレッドがその項目 を取得 できるようになります。acquire()
が呼 び出 されたとき、同期 ロックは保持 されないことに注意 してください。同期 ロックが保持 されると、項目 がプールに返 されなくなるためです。 セマフォは、プールへのアクセスを制限 する必要 のある同期 を、プール自体 の一貫 性 を維持 するために必要 な同期 からは分離 してカプセル化 します。値 を1に初期 化 されたセマフォは、利用 できるパーミットが最大 で1個 であるセマフォとして使用 されるため、相互 排他 ロックとして利用 できます。 これは一般 的 には2進 型 セマフォと呼 ばれます。利用 可能 なパーミットが1つか、または利用 可能 なパーミットがないかの2つの状態 しかないためです。 このように使用 された場合 、多 くのLock
実装 とは異 なり、2進 型 セマフォには、所有 者 以外 のスレッドでロックを解放 できるという特性 があります(セマフォには所有 権 の概念 がないため)。 これは、デッドロックの回復 のような特殊 なコンテキストで便利 です。このクラスのコンストラクタは、オプションで
公平 性 パラメータを受 け入 れます。 falseに設定 すると、このクラスはスレッドがパーミットを取得 する順序 について保証 しません。特 に、バージ(barging)が許可 されています。つまり、acquire()
を呼 び出 すスレッドに、待機 していたスレッドより先 にパーミットを割 り当 てることができます。論理 的 には、新 しいスレッドが、待機 中 のスレッドのキューの先頭 に配置 されます。公平 性 がtrueに設定 されると、セマフォは、acquire
メソッドのいずれかを呼 び出 すスレッドが、これらのメソッドの呼出 しが処理 された順序 (先入 れ先出 し、FIFO)でパーミットを取得 するように選択 されることを保証 します。 FIFO順序 付 けは、必然 的 にこれらのメソッド内 の特定 の内部 実行 ポイントに適用 されます。 そのため、あるスレッドが別 のスレッドより前 にacquire
を呼 び出 しても、そのスレッドよりあとに順序付 けポイントに到達 する可能 性 があります。また、メソッドからの復帰 時 も同様 です。 また、時間 指定 のないtryAcquire
メソッドは公平 性 の設定 に従 いませんが、利用 可能 なパーミットをすべて取得 することにも注意 してください。通常 、リソース・アクセスを制御 するために使用 されるセマフォは、リソースへのアクセスができないスレッドがないよう、公平 に初期 化 される必要 があります。 ほかの種類 の同期 制御 にセマフォを使用 する場合 は、公平 性 を考慮 するよりも不公平 な順序 付 けによるスループットの利点 のほうがしばしば重要 になります。このクラスはまた、
複数 のパーミットに対 して同時 にacquire
やrelease
を実行 するための簡易 メソッドも提供 します。 これらのメソッドは一般 に、ループより効率 的 かつ効果 的 である。 ただし、優先 順位 は設定 されません。 たとえば、スレッドAがs.acquire(3
を呼 び出 し、スレッドBがs.acquire(2)
を呼 び出 し、2つの許可 が利用 可能 になると、その獲得 が最初 に行 われ、Semaphores
がフェア・モードでない限 り、スレッドBがそれらを取得 する保証 はありません。メモリー
整合 性 効果 :release()
などの「解放 」メソッドを呼 び出 す前 のスレッド内 のアクションは、別 のスレッド内 のacquire()
などの正常 終了 した「取得 」メソッドに続 くアクションの前 に発生 します。導入 されたバージョン:- 1.5
関連 項目 :直列 化 された形式
- すべての
-
-
メソッドのサマリー
すべてのメソッド インスタンス・メソッド 具象 メソッド修飾 子 と型 メソッド 説明 void
acquire()
このセマフォからパーミットを取得 します。パーミットが利用 可能 になるか、またはスレッドが割 り込 みされるまでブロックします。void
acquire(int permits)
このセマフォから指定 された数 のパーミットを取得 します。すべてのパーミットが利用 可能 になるか、またはスレッドが割 り込 みされるまでブロックします。void
acquireUninterruptibly()
このセマフォからパーミットを取得 します。パーミットが利用 可能 になるまでブロックします。void
acquireUninterruptibly(int permits)
このセマフォから指定 された数 のパーミットを取得 します。すべてのパーミットが利用 可能 になるまでブロックします。int
availablePermits()
このセマフォで現在 利用 可能 なパーミットの数 を返 します。int
drainPermits()
すぐに利用 可能 なすべての許可 を取得 して返 します。または、否定 的 な許可 が利用 可能 な場合 は、それらを解放 します。protected Collection<Thread>
getQueuedThreads()
パーミットの取得 を待機 しているスレッドを含 むコレクションを返 します。int
getQueueLength()
パーミットの取得 を待機 しているスレッドの推定 数 を返 します。boolean
hasQueuedThreads()
パーミットの取得 を待機 中 のスレッドが存在 するかどうかを照会 します。boolean
isFair()
このセマフォで公平 性 がtrueに設定 されている場合 はtrue
を返 します。protected void
reducePermits(int reduction)
指定 されたreductionの数 だけ利用 可能 なパーミットの数 を減 らします。void
release()
パーミットを解放 し、セマフォに戻 します。void
release(int permits)
指定 された数 のパーミットを解放 し、セマフォに戻 します。String
toString()
セマフォおよびその状態 を識別 する文字 列 を返 します。boolean
tryAcquire()
パーミットが呼出 し時 に利用 可能 な場合 に限 り、このセマフォからパーミットを取得 します。boolean
tryAcquire(int permits)
指定 された数 のパーミットが呼出 し時 に利用 可能 な場合 に限 り、それらすべてのパーミットを取得 します。boolean
tryAcquire(int permits, long timeout, TimeUnit unit)
指定 された待機 時間 内 で指定 された数 のパーミットが利用 可能 であり、現在 のスレッドで割 り込 みが発生 していない場合 に、このセマフォから指定 された数 のパーミットを取得 します。boolean
tryAcquire(long timeout, TimeUnit unit)
指定 された待機 時間 内 でパーミットが利用 可能 になり、現在 のスレッドで割 り込 みが発生 していない場合 に、このセマフォからパーミットを取得 します。
-
-
-
コンストラクタの
詳細 -
Semaphore
public Semaphore(int permits)
指定 された数 のパーミットと不公平 な公平 性 設定 を使用 して、Semaphore
を作成 します。- パラメータ:
permits
-利用 可能 なパーミットの初期 の数 。 この値 は負 にすることも可能 で、その場合 は取得 メソッドが許可 を受 け取 る前 に解放 が発生 する必要 がある。
-
Semaphore
public Semaphore(int permits, boolean fair)
指定 された数 のパーミットと指定 された公平 性 設定 を使用 して、Semaphore
を作成 します。- パラメータ:
permits
-利用 可能 なパーミットの初期 の数 。 この値 は負 にすることも可能 で、その場合 は取得 メソッドが許可 を受 け取 る前 に解放 が発生 する必要 がある。fair
- このセマフォが競合 時 にパーミットの許可 を先入 れ先出 しで保証 する場合 はtrue
。それ以外 の場合 はfalse
-
-
メソッドの
詳細 -
acquire
public void acquire() throws InterruptedException
このセマフォからパーミットを取得 します。パーミットが利用 可能 になるか、またはスレッドが割 り込 みされるまでブロックします。パーミットが
利用 可能 な場合 はパーミットを取得 してすぐに復帰 するため、利用 可能 なパーミットの数 は1つずつ減 ります。パーミットが
利用 可能 でない場合 、現在 のスレッドはスレッドのスケジューリングに関 して無効 になり、次 の2つのいずれかが起 きるまで待機 します。現在 のスレッドで、- このメソッドへのエントリ
上 で設定 された割込 みステータスが保持 されるか、 - パーミットの
待機 中 に割 り込 みが発生 した場合 、
InterruptedException
がスローされ、現在 のスレッドの割込 みステータスがクリアされます。例外 :InterruptedException
-現在 のスレッドで割込 みが発生 した場合
- このメソッドへのエントリ
-
acquireUninterruptibly
public void acquireUninterruptibly()
このセマフォからパーミットを取得 します。パーミットが利用 可能 になるまでブロックします。パーミットが
利用 可能 な場合 はパーミットを取得 してすぐに復帰 するため、利用 可能 なパーミットの数 は1つずつ減 ります。パーミットが
使用 できない場合 、現在 のスレッドはスレッドのスケジューリングの目的 に対 して無効 になり、ほかのいずれかのスレッドがこのセマフォのrelease()
メソッドを呼 び出 して、現在 のスレッドが次 にパーミットを割 り当 てられるスレッドになるまで、現在 のスレッドは待機 します。パーミットの
待機 中 に現在 のスレッドが割 り込 みされると、待機 は続行 しますが、スレッドにパーミットが割 り当 てられるタイミングは、割込 みが発生 しなかった場合 にパーミットを受 け取 るはずのタイミングとは異 なることがあります。 スレッドがこのメソッドから復帰 すると、その割込 み状態 が設定 されます。
-
tryAcquire
public boolean tryAcquire()
パーミットが呼出 し時 に利用 可能 な場合 に限 り、このセマフォからパーミットを取得 します。パーミットが
利用 可能 な場合 はパーミットを取得 して値 true
ですぐに復帰 するため、利用 可能 なパーミットの数 は1つずつ減 ります。パーミットが
利用 可能 でない場合 、このメソッドは値 false
ですぐに復帰 します。このセマフォが
公平 順序付 けポリシーを使用 するように設定 されている場合 でも、パーミットが利用 可能 であれば、ほかのスレッドが現在 待機 しているかどうかに関係 なく、tryAcquire()
の呼出 しですぐにパーミットを取得 します。 この「バージ」(barging)動作 により公平 性 が失 われるとは言 え、これは特定 の状況 下 で有用 です。公平 性 設定 を尊重 する場合 は、ほぼ等価 なtryAcquire(0, TimeUnit.SECONDS)
を使用 します(これも割込 みを検出 する)。戻 り値 :- パーミットが
取得 された場合 はtrue
。それ以外 の場合 はfalse
-
tryAcquire
public boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException
指定 された待機 時間 内 でパーミットが利用 可能 になり、現在 のスレッドで割 り込 みが発生 していない場合 に、このセマフォからパーミットを取得 します。パーミットが
利用 可能 な場合 はパーミットを取得 して値 true
ですぐに復帰 するため、利用 可能 なパーミットの数 は1つずつ減 ります。パーミットが
利用 可能 でない場合 、現在 のスレッドはスレッドのスケジューリングに関 して無効 になり、次 の3つのいずれかが起 きるまで待機 します。- ほかのスレッドがこのセマフォに
対 してrelease()
メソッドを呼 び出 し、現在 のスレッドが次 にパーミットを割 り当 てられるスレッドになる。 - ほかのスレッドが
現在 のスレッドに割 り込 みを行 う。または 指定 された待機 時間 が経過 する。
パーミットが
取得 された場合 は、値 true
が返 されます。現在 のスレッドで、- このメソッドへのエントリ
上 で設定 された割込 みステータスが保持 されるか、 - パーミットの
取得 の待機 中 に割 り込 みが発生 した場合 、
InterruptedException
がスローされ、現在 のスレッドの割込 みステータスがクリアされます。指定 された待機 時間 が経過 すると、値 false
が返 されます。時間 がゼロまたはそれより小 さい場合 、メソッドは待機 しません。- パラメータ:
timeout
- パーミットの最長 待機 時間 unit
-timeout
引数 の時間 単位 戻 り値 :- パーミットが
取得 された場合 はtrue
。パーミットが取得 される前 に待機 時間 が経過 した場合 はfalse
例外 :InterruptedException
-現在 のスレッドで割込 みが発生 した場合
- ほかのスレッドがこのセマフォに
-
release
public void release()
パーミットを解放 し、セマフォに戻 します。パーミットを
解放 すると、利用 可能 なパーミットの数 が1つずつ増 えます。 いくつかのスレッドがパーミットを取得 しようと試 みている場合 は、その中 の1つのスレッドが選択 され、解放 されたばかりのパーミットが与 えられます。 そのスレッドは、スレッドのスケジューリングに関 して(ふたたび)有効 になります。パーミットを
解放 するスレッドは、acquire()
の呼出 しでそのパーミットを取得 している必要 はありません。 セマフォの適切 な使用 法 は、アプリケーションでのプログラミング規約 で確立 されます。
-
acquire
public void acquire(int permits) throws InterruptedException
このセマフォから指定 された数 のパーミットを取得 します。すべてのパーミットが利用 可能 になるか、またはスレッドが割 り込 みされるまでブロックします。指定 された数 のパーミットが利用 可能 な場合 はパーミットを取得 してすぐに復帰 するため、利用 可能 なパーミットの数 は指定 された数 ずつ減 ります。 このメソッドは、ループをfor (int i = 0; i < permits; ++i) acquire();
と同 じ効果 がありますが、パーツを原子 的 にまとめて取得 する点 が異 なります:十分 な数 のパーミットが利用 可能 でない場合 、現在 のスレッドはスレッドのスケジューリングに関 して無効 になり、次 の2つのいずれかが起 きるまで待機 します。他 のスレッドはこのセマフォのrelease
メソッドの1つを呼 び出 し、現在 のスレッドは次 に許可 を割 り当 てられ、使用 可能 な許可 の数 がこのリクエストを満 たします。または- ほかのスレッドが
現在 のスレッドに割 り込 みを行 う。
現在 のスレッドで、- このメソッドへのエントリ
上 で設定 された割込 みステータスが保持 されるか、 - パーミットの
待機 中 に割 り込 みが発生 した場合 、
InterruptedException
がスローされ、現在 のスレッドの割込 みステータスがクリアされます。 このスレッドに割 り当 てられるはずだったすべてのパーミットは、release()
の呼出 しでパーミットが利用 可能 になったかのように、パーミットの取得 を試 みる別 のスレッドに割 り当 てられます。- パラメータ:
permits
-取得 するパーミットの数 例外 :InterruptedException
-現在 のスレッドで割込 みが発生 した場合 IllegalArgumentException
-permits
が負 である場合
-
acquireUninterruptibly
public void acquireUninterruptibly(int permits)
このセマフォから指定 された数 のパーミットを取得 します。すべてのパーミットが利用 可能 になるまでブロックします。指定 された数 のパーミットが利用 可能 な場合 はパーミットを取得 してすぐに復帰 するため、利用 可能 なパーミットの数 は指定 された数 ずつ減 ります。 このメソッドは、ループをfor (int i = 0; i < permits; ++i) acquireUninterruptibly();
と同 じ効果 がありますが、パーツを原子 的 にまとめて取得 する点 が異 なります:不十分 な許可 が利用 可能 な場合 、現在 のスレッドはスレッド・スケジューリングの目的 で無効 になり、他 のスレッドがこのセマフォのrelease
メソッドの1つを呼 び出 し、現在 のスレッドが次 に許可 を割 り当 てられ、利用 可能 な許可 の数 がこのリクエストを満 たすまで。現在 のスレッドがパーミットの待機 中 に割 り込 まれた場合 、待機 を続行 します。キュー内 での現在 のスレッドの位置 には影響 ありません。 スレッドがこのメソッドから復帰 すると、その割込 み状態 が設定 されます。- パラメータ:
permits
-取得 するパーミットの数 例外 :IllegalArgumentException
-permits
が負 である場合
-
tryAcquire
public boolean tryAcquire(int permits)
指定 された数 のパーミットが呼出 し時 に利用 可能 な場合 に限 り、それらすべてのパーミットを取得 します。指定 された数 のパーミットが利用 可能 な場合 はパーミットを取得 して値 true
ですぐに復帰 するため、利用 可能 なパーミットの数 は指定 された数 ずつ減 ります。十分 な数 のパーミットが利用 可能 でない場合 、このメソッドは値 false
ですぐに復帰 し、利用 可能 なパーミットの数 は変化 しません。このセマフォが
公平 順序付 けポリシーを使用 するように設定 されている場合 でも、パーミットが利用 可能 であれば、ほかのスレッドが現在 待機 しているかどうかに関係 なく、tryAcquire
の呼出 しですぐにパーミットを取得 します。 この「バージ」(barging)動作 により公平 性 が失 われるとは言 え、これは特定 の状況 下 で有用 です。公平 性 設定 を尊重 する場合 は、ほぼ等価 なtryAcquire(permits, 0, TimeUnit.SECONDS)
を使用 します(これも割込 みを検出 する)。- パラメータ:
permits
-取得 するパーミットの数 戻 り値 :- パーミットが
取得 された場合 はtrue
。それ以外 の場合 はfalse
例外 :IllegalArgumentException
-permits
が負 である場合
-
tryAcquire
public boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InterruptedException
指定 された待機 時間 内 で指定 された数 のパーミットが利用 可能 であり、現在 のスレッドで割 り込 みが発生 していない場合 に、このセマフォから指定 された数 のパーミットを取得 します。指定 された数 のパーミットが利用 可能 な場合 はパーミットを取得 して値 true
ですぐに復帰 するため、利用 可能 なパーミットの数 は指定 された数 ずつ減 ります。十分 な数 のパーミットが利用 可能 でない場合 、現在 のスレッドはスレッドのスケジューリングに関 して無効 になり、次 の3つのいずれかが起 きるまで待機 します。他 のスレッドはこのセマフォのrelease
メソッドの1つを呼 び出 し、現在 のスレッドは次 に許可 を割 り当 てられ、使用 可能 な許可 の数 がこのリクエストを満 たします。または- ほかのスレッドが
現在 のスレッドに割 り込 みを行 う。または 指定 された待機 時間 が経過 する。
パーミットが
取得 された場合 は、値 true
が返 されます。現在 のスレッドで、- このメソッドへのエントリ
上 で設定 された割込 みステータスが保持 されるか、 - パーミットの
取得 の待機 中 に割 り込 みが発生 した場合 、
InterruptedException
がスローされ、現在 のスレッドの割込 みステータスがクリアされます。 このスレッドに割 り当 てられるはずだったすべてのパーミットは、release()
の呼出 しでパーミットが利用 可能 になったかのように、パーミットの取得 を試 みる別 のスレッドに割 り当 てられます。指定 された待機 時間 が経過 すると、値 false
が返 されます。時間 がゼロまたはそれより小 さい場合 、メソッドは待機 しません。 このスレッドに割 り当 てられるはずだったすべてのパーミットは、release()
の呼出 しでパーミットが利用 可能 になったかのように、パーミットの取得 を試 みる別 のスレッドに割 り当 てられます。- パラメータ:
permits
-取得 するパーミットの数 timeout
- パーミットの最長 待機 時間 unit
-timeout
引数 の時間 単位 戻 り値 :- すべてのパーミットが
取得 された場合 はtrue
。すべてのパーミットが取得 される前 に待機 時間 が経過 した場合 はfalse
例外 :InterruptedException
-現在 のスレッドで割込 みが発生 した場合 IllegalArgumentException
-permits
が負 である場合
-
release
public void release(int permits)
指定 された数 のパーミットを解放 し、セマフォに戻 します。指定 された数 のパーミットを解放 すると、利用 可能 なパーミットの数 がその分 増 えます。許可 を取得 しようとしているスレッドがあれば、1つのスレッドが選択 され、今 リリースされた許可 が与 えられます。利用 可能 なパーミットの数 がそのスレッドの要求 を満 たす場合 、そのスレッドはスレッドのスケジューリングに関 して(ふたたび)有効 になります。そうでない場合 、十分 なパーミットが利用 可能 になるまでスレッドは待機 します。 このスレッドの要求 を満 たしたあとも引 き続 きパーミットが利用 可能 な場合 、それらのパーミットはパーミットを取得 しようとしている別 のスレッドに割 り当 てられます。パーミットを
解放 するスレッドは、acquire
の呼出 しでそのパーミットを取得 している必要 はありません。 セマフォの適切 な使用 法 は、アプリケーションでのプログラミング規約 で確立 されます。- パラメータ:
permits
-解放 するパーミットの数 例外 :IllegalArgumentException
-permits
が負 である場合
-
availablePermits
public int availablePermits()
このセマフォで現在 利用 可能 なパーミットの数 を返 します。通常 、このメソッドはデバッグとテストの場合 に使用 します。戻 り値 :- このセマフォで
利用 可能 なパーミットの数
-
drainPermits
public int drainPermits()
すぐに利用 可能 なすべての許可 を取得 して返 します。または、否定 的 な許可 が利用 可能 な場合 は、それらを解放 します。返却 時 には、ゼロ許可 が利用 可能 です。戻 り値 :取得 された許可 の数 、または、もしあれば、リリースされた数
-
reducePermits
protected void reducePermits(int reduction)
指定 されたreductionの数 だけ利用 可能 なパーミットの数 を減 らします。 このメソッドは、利用 不可能 になるリソースを追跡 するためにセマフォを使用 するサブクラスで有用 です。 パーミットが利用 可能 になるまでブロックして待機 しない点 で、このメソッドはacquire
と異 なります。- パラメータ:
reduction
-削除 するパーミットの数 例外 :IllegalArgumentException
-reduction
が負 である場合
-
isFair
public boolean isFair()
このセマフォで公平 性 がtrueに設定 されている場合 はtrue
を返 します。戻 り値 :- このセマフォで
公平 性 がtrueに設定 されている場合 はtrue
-
hasQueuedThreads
public final boolean hasQueuedThreads()
パーミットの取得 を待機 中 のスレッドが存在 するかどうかを照会 します。取消 しはいつでも発生 する可能 性 があるため、true
が返 されても、ほかのいずれかのスレッドが取得 するとは保証 されていないことに注意 してください。 このメソッドは、主 にシステム状態 の監視 に使用 する目的 で設計 されています。戻 り値 :- ロックの
取得 を待機 中 のほかのスレッドが存在 する可能 性 がある場合 はtrue
-
getQueueLength
public final int getQueueLength()
パーミットの取得 を待機 しているスレッドの推定 数 を返 します。 このメソッドが内部 のデータ構造 をトラバースしている間 にも、スレッド数 が動的 に変化 する場合 があるため、この値 は推定 に過 ぎません。 このメソッドは、同期 の制御 用 としてではなく、システム状態 の監視 用 として設計 されています。戻 り値 :- このロックを
待機 しているスレッドの推定 数
-
getQueuedThreads
protected Collection<Thread> getQueuedThreads()
パーミットの取得 を待機 しているスレッドを含 むコレクションを返 します。実際 のスレッド・セットは、結果 の構築 中 にも動的 に変化 する可能 性 があるため、返 されるコレクションは最善 の努力 を払 った上 での推定 に過 ぎません。返 されるコレクションの要素 には、特定 の順序 は存在 しません。 このメソッドは、より包括 的 な監視 機能 を提供 するサブクラスの構築 を容易 にする目的 で設計 されています。戻 り値 :- スレッドのコレクション
-
-