モジュール java.base

クラスLockSupport

java.lang.Object
java.util.concurrent.locks.LockSupport

public class LockSupport extends Object
ロックおよびほかの同期クラスを作成するための、基本的なスレッド・ブロック・プリミティブです。

このクラスは、それを使用している各スレッドにパーミットを(Semaphoreクラスという意味で)関連付けます。 パーミットが使用可能な場合、parkの呼出しはただちに復帰し、プロセス内でそのパーミットを消費します。それ以外の場合は、ブロックされる可能性があります unparkの呼出しによって、パーミットがまだ使用可能でなかった場合は使用可能になります。 (ただし、Semaphoreとは異なり、パーミットでは累積は実行されません。 最大で1つしか存在しません。) 確実に使用するには、揮発性(または原子)変数を使用して、パークまたはパーク解除するタイミングを制御する必要があります。 これらのメソッドへのコールの順序は、揮発性変数アクセスに関して維持されますが、必ずしも不揮発性変数アクセスとはかぎりません。

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を仲介的に使用すると、応答しないスレッド(a "敗北")が発生する可能性があります。

使用例。 次に、先入れ先出しの再入不可能なロック・クラスの概略を示します。

 
 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