このクラスは、それを使用している各スレッドにパーミットを(Semaphore
クラスという意味で)関連付けます。 パーミットが使用可能な場合、park
の呼出しはただちに復帰し、プロセス内でそのパーミットを消費します。それ以外の場合は、ブロックされる可能性があります。 unpark
の呼出しによって、パーミットがまだ使用可能でなかった場合は使用可能になります。 (ただし、Semaphoreとは異なり、パーミットでは累積は実行されません。 最大で1つしか存在しません。) 信頼性の高い使用法では、パークするかアンカーするかを制御するために、volatile変数(または原子)を使用する必要があります。 これらのメソッドへの呼び出しの順序は、揮発性の可変アクセスに関しては維持されますが、必ずしも不揮発性の可変アクセスではありません。
park
メソッドとunpark
メソッドは、非推奨メソッドThread.suspend
およびThread.resume
をこのような目的に使用できなくなるような問題が発生しないスレッドをブロックおよびブロック解除するための効率的な手段を提供します。park
を呼び出しているあるスレッドと、そのスレッドのunpark
を試みている別のスレッドの間の競合は、パーミットのために活発な状態を保持します。 さらに、呼出し側のスレッドで割込みが発生し、かつタイムアウト・バージョンがサポートされている場合は、park
が復帰します。 park
メソッドはまた「理由なしで」いつでも復帰する可能性があるため、一般には、復帰時に状態を再チェックするループ内で呼び出す必要があります。 この意味で、park
はスピンにそれほどの時間を浪費しない「ビジー待機」の最適化として機能しますが、効果を発揮させるにはunpark
とペアにする必要があります。
park
の3つの形式でも、それぞれblocker
オブジェクト・パラメータをサポートします。 スレッドがブロックされるとこのオブジェクトが記録されるため、監視および診断ツールでスレッドがブロックされた理由を特定することができます。 (このようなツールは、getBlocker(Thread)
メソッドを使用してブロッカにアクセスできます。) このパラメータを指定しない元の形式ではなくこれらの形式を使用することを強くお薦めします。 ロック実装内のblocker
として指定する通常の引数はthis
です。
これらのメソッドは、高度な同期ユーティリティの作成用ツールとして使用するように設計されており、それ自体では、たいていの同時制御アプリケーションでは有用ではありません。 park
メソッドは、次の形式の構築でのみ使用するように設計されています。
while (!canProceed()) {
// ensure request to unpark is visible to other threads
...
LockSupport.park(this);
}
park
への呼び出しに先立ち、ロック解除またはブロッキングを伴うロック解除リクエストをパブリッシュするスレッドによるアクションはありません。 各スレッドには1つの許可のみが関連付けられているため、暗黙的にクラスをロードすることを含め、park
を仲介して使用すると、応答のないスレッド("敗北")が発生する可能性があります。
使用例。 次に、先入れ先出しの再入不可能なロック・クラスの概略を示します。
class FIFOMutex {
private final AtomicBoolean locked = new AtomicBoolean(false);
private final Queue<Thread> waiters
= new ConcurrentLinkedQueue<>();
public void lock() {
boolean wasInterrupted = false;
// publish current thread for unparkers
waiters.add(Thread.currentThread());
// Block while not first in queue or cannot acquire lock
while (waiters.peek() != Thread.currentThread() ||
!locked.compareAndSet(false, true)) {
LockSupport.park(this);
// ignore interrupts while waiting
if (Thread.interrupted())
wasInterrupted = true;
}
waiters.remove();
// ensure correct interrupt status on return
if (wasInterrupted)
Thread.currentThread().interrupt();
}
public void unlock() {
locked.set(false);
LockSupport.unpark(waiters.peek());
}
static {
// Reduce the risk of "lost unpark" due to classloading
Class<?> ensureLoaded = LockSupport.class;
}
}
- 導入されたバージョン:
- 1.5
-
メソッドのサマリー
修飾子と型メソッド説明static Object
getBlocker
(Thread t) まだブロック解除されていないparkメソッドの最新の呼出しに指定されたブロッカ・オブジェクトを返します。ブロックされていない場合はnullを返します。static void
park()
パーミットが利用可能でない場合、スレッドのスケジューリングに関して現在のスレッドを無効にします。static void
パーミットが利用可能でない場合、スレッドのスケジューリングに関して現在のスレッドを無効にします。static void
parkNanos
(long nanos) パーミットが利用可能である場合を除き、現在のスレッドを、指定された待機時間までスレッド・スケジューリングに関して無効にします。static void
パーミットが利用可能である場合を除き、現在のスレッドを、指定された待機時間までスレッド・スケジューリングに関して無効にします。static void
parkUntil
(long deadline) パーミットが利用可能でない場合、指定された期限まで、スレッドのスケジューリングに関して現在のスレッドを無効にします。static void
パーミットが利用可能でない場合、指定された期限まで、スレッドのスケジューリングに関して現在のスレッドを無効にします。static void
setCurrentBlocker
(Object blocker) 現行のスレッドのgetBlocker
の呼出しで返されるオブジェクトを設定します。static void
指定されたスレッドのパーミットが使用可能でない場合に、使用可能にします。
-
メソッドの詳細
-
setCurrentBlocker
public static void setCurrentBlocker(Object blocker) 現行のスレッドのgetBlocker
の呼出しで返されるオブジェクトを設定します。 このメソッドは、非パブリック・オブジェクトからpark()
の引数なしのバージョンを起動する前に使用でき、より役立つ診断を可能にし、以前のブロックしているメソッドの実装との互換性を維持します。 ブロッカの前の値は、ブロック後に自動的にリストアされません。park(b
の効果を得るには、setCurrentBlocker(b); park(); setCurrentBlocker(null);
を使用- パラメータ:
blocker
- ブロッカ・オブジェクト- 導入されたバージョン:
- 14
-
unpark
public static void unpark(Thread thread) 指定されたスレッドのパーミットが使用可能でない場合に、使用可能にします。 スレッドがpark
でブロックされた場合は、ブロックを解除します。 それ以外の場合は、そのpark
の次回の呼出しがブロックされないよう保証されます。 指定されたスレッドが起動していない場合、この操作の効果は一切保証されません。- パラメータ:
thread
- unparkを実行するスレッドまたはnull
。その場合、この操作に効果はない
-
park
public static void park(Object blocker) パーミットが利用可能でない場合、スレッドのスケジューリングに関して現在のスレッドを無効にします。パーミットが使用可能な場合、これは消費され、呼出しはただちに復帰します。それ以外の場合、現在のスレッドは、スレッド・スケジューリングに関して無効になり、次の3つのいずれかが起きるまで待機します。
このメソッドは、これらのどれがメソッド復帰の原因となったかはレポートしません。 呼出し側は、スレッドの初回parkの原因となった状態を再チェックする必要があります。 呼出し側は、復帰時のスレッドの割込み状態なども判定できます。
- パラメータ:
blocker
- このスレッドのparkを行う同期オブジェクト- 導入されたバージョン:
- 1.6
-
parkNanos
public static void parkNanos(Object blocker, long nanos) パーミットが利用可能である場合を除き、現在のスレッドを、指定された待機時間までスレッド・スケジューリングに関して無効にします。指定した待機時間がゼロまたは負の場合、メソッドは何も実行しません。 それ以外の場合、許可が消費され、呼出しはただちに返されます。それ以外の場合は、現在のスレッドがスレッドのスケジューリングに関して無効になり、4つのうちの1つが起きるまで待機します:
- ほかのスレッドが、現在のスレッドをターゲットとして
unpark
を呼び出す。 - ほかのスレッドが現在のスレッドに割り込みを行う。または
- 指定された待機時間が経過する。または
- 呼出しが、見せかけで(理由もなく)復帰する。
このメソッドは、これらのどれがメソッド復帰の原因となったかはレポートしません。 呼出し側は、スレッドの初回parkの原因となった状態を再チェックする必要があります。 呼出し側は、スレッドの割込み状態や、復帰時の経過時間なども判定できます。
- パラメータ:
blocker
- このスレッドのparkを行う同期オブジェクトnanos
- 待機する最大ナノ秒数- 導入されたバージョン:
- 1.6
- ほかのスレッドが、現在のスレッドをターゲットとして
-
parkUntil
public static void parkUntil(Object blocker, long deadline) パーミットが利用可能でない場合、指定された期限まで、スレッドのスケジューリングに関して現在のスレッドを無効にします。パーミットが使用可能な場合、これは消費され、呼出しはただちに復帰します。それ以外の場合、現在のスレッドは、スレッド・スケジューリングに関して無効になり、次の4つのいずれかが起きるまで待機します。
- ほかのスレッドが、現在のスレッドをターゲットとして
unpark
を呼び出す。 - ほかのスレッドが現在のスレッドに割り込みを行う。または
- 指定された期限が経過する。または
- 呼出しが、見せかけで(理由もなく)復帰する。
このメソッドは、これらのどれがメソッド復帰の原因となったかはレポートしません。 呼出し側は、スレッドの初回parkの原因となった状態を再チェックする必要があります。 呼出し側は、スレッドの割込み状態や、復帰時の現在時刻なども判定できます。
- パラメータ:
blocker
- このスレッドのparkを行う同期オブジェクトdeadline
- 待機用の、元期からのミリ秒単位の絶対時間- 導入されたバージョン:
- 1.6
- ほかのスレッドが、現在のスレッドをターゲットとして
-
getBlocker
まだブロック解除されていないparkメソッドの最新の呼出しに指定されたブロッカ・オブジェクトを返します。ブロックされていない場合はnullを返します。 返される値は、瞬間的なスナップショットです。そのため、スレッドは別のブロッカ・オブジェクトでブロック解除されていることもブロックされていることもあります。- パラメータ:
t
- スレッド- 戻り値:
- ブロッカ
- 例外:
NullPointerException
- 引数がnullの場合- 導入されたバージョン:
- 1.6
-
park
public static void park()パーミットが利用可能でない場合、スレッドのスケジューリングに関して現在のスレッドを無効にします。パーミットが使用可能な場合、これは消費され、呼出しはただちに復帰します。それ以外の場合、現在のスレッドは、スレッド・スケジューリングに関して無効になり、次の3つのいずれかが起きるまで待機します。
このメソッドは、これらのどれがメソッド復帰の原因となったかはレポートしません。 呼出し側は、スレッドの初回parkの原因となった状態を再チェックする必要があります。 呼出し側は、復帰時のスレッドの割込み状態なども判定できます。
-
parkNanos
public static void parkNanos(long nanos) パーミットが利用可能である場合を除き、現在のスレッドを、指定された待機時間までスレッド・スケジューリングに関して無効にします。指定した待機時間がゼロまたは負の場合、メソッドは何も実行しません。 それ以外の場合、許可が消費され、呼出しはただちに返されます。それ以外の場合は、現在のスレッドがスレッドのスケジューリングに関して無効になり、4つのうちの1つが起きるまで待機します:
- ほかのスレッドが、現在のスレッドをターゲットとして
unpark
を呼び出す。 - ほかのスレッドが現在のスレッドに割り込みを行う。または
- 指定された待機時間が経過する。または
- 呼出しが、見せかけで(理由もなく)復帰する。
このメソッドは、これらのどれがメソッド復帰の原因となったかはレポートしません。 呼出し側は、スレッドの初回parkの原因となった状態を再チェックする必要があります。 呼出し側は、スレッドの割込み状態や、復帰時の経過時間なども判定できます。
- パラメータ:
nanos
- 待機する最大ナノ秒数
- ほかのスレッドが、現在のスレッドをターゲットとして
-
parkUntil
public static void parkUntil(long deadline) パーミットが利用可能でない場合、指定された期限まで、スレッドのスケジューリングに関して現在のスレッドを無効にします。パーミットが使用可能な場合、これは消費され、呼出しはただちに復帰します。それ以外の場合、現在のスレッドは、スレッド・スケジューリングに関して無効になり、次の4つのいずれかが起きるまで待機します。
- ほかのスレッドが、現在のスレッドをターゲットとして
unpark
を呼び出す。 - ほかのスレッドが現在のスレッドに割り込みを行う。または
- 指定された期限が経過する。または
- 呼出しが、見せかけで(理由もなく)復帰する。
このメソッドは、これらのどれがメソッド復帰の原因となったかはレポートしません。 呼出し側は、スレッドの初回parkの原因となった状態を再チェックする必要があります。 呼出し側は、スレッドの割込み状態や、復帰時の現在時刻なども判定できます。
- パラメータ:
deadline
- 待機用の、元期からのミリ秒単位の絶対時間
- ほかのスレッドが、現在のスレッドをターゲットとして
-