モジュール java.base

クラスLockSupport


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

    このクラスは、それを使用している各スレッドにパーミットを(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メソッド 具象メソッド 
      修飾子と型 メソッド 説明
      static Object getBlocker​(Thread t)
      まだブロック解除されていないparkメソッドの最新の呼出しに指定されたブロッカ・オブジェクトを返します。ブロックされていない場合はnullを返します。
      static void park()
      パーミットが利用可能でない場合、スレッドのスケジューリングに関して現在のスレッドを無効にします。
      static void park​(Object blocker)
      パーミットが利用可能でない場合、スレッドのスケジューリングに関して現在のスレッドを無効にします。
      static void parkNanos​(long nanos)
      パーミットが利用可能である場合を除き、現在のスレッドを、指定された待機時間までスレッド・スケジューリングに関して無効にします。
      static void parkNanos​(Object blocker, long nanos)
      パーミットが利用可能である場合を除き、現在のスレッドを、指定された待機時間までスレッド・スケジューリングに関して無効にします。
      static void parkUntil​(long deadline)
      パーミットが利用可能でない場合、指定された期限まで、スレッドのスケジューリングに関して現在のスレッドを無効にします。
      static void parkUntil​(Object blocker, long deadline)
      パーミットが利用可能でない場合、指定された期限まで、スレッドのスケジューリングに関して現在のスレッドを無効にします。
      static void unpark​(Thread thread)
      指定されたスレッドのパーミットが使用可能でない場合に、使用可能にします。
    • メソッドの詳細

      • unpark

        public static void unpark​(Thread thread)
        指定されたスレッドのパーミットが使用可能でない場合に、使用可能にします。 スレッドがparkでブロックされた場合は、ブロックを解除します。 それ以外の場合は、そのparkの次回の呼出しがブロックされないよう保証されます。 指定されたスレッドが起動していない場合、この操作の効果は一切保証されません。
        パラメータ:
        thread - unparkを実行するスレッドまたはnull。その場合、この操作に効果はない
      • park

        public static void park​(Object blocker)
        パーミットが利用可能でない場合、スレッドのスケジューリングに関して現在のスレッドを無効にします。

        パーミットが使用可能な場合、これは消費され、呼出しはただちに復帰します。それ以外の場合、現在のスレッドは、スレッド・スケジューリングに関して無効になり、次の3つのいずれかが起きるまで待機します。

        • ほかのスレッドが、現在のスレッドをターゲットとしてunparkを呼び出す。
        • ほかのスレッドが現在のスレッドに割り込みを行う。または
        • 呼出しが、見せかけで(理由もなく)復帰する。

        このメソッドは、これらのどれがメソッド復帰の原因となったかはレポートしません 呼出し側は、スレッドの初回parkの原因となった状態を再チェックする必要があります。 呼出し側は、復帰時のスレッドの割込み状態なども判定できます。

        パラメータ:
        blocker - このスレッドのparkを行う同期オブジェクト
        導入されたバージョン:
        1.6
      • parkNanos

        public static void parkNanos​(Object blocker,
                                     long nanos)
        パーミットが利用可能である場合を除き、現在のスレッドを、指定された待機時間までスレッド・スケジューリングに関して無効にします。

        パーミットが使用可能な場合、これは消費され、呼出しはただちに復帰します。それ以外の場合、現在のスレッドは、スレッド・スケジューリングに関して無効になり、次の4つのいずれかが起きるまで待機します。

        • ほかのスレッドが、現在のスレッドをターゲットとして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

        public static Object getBlocker​(Thread t)
        まだブロック解除されていないparkメソッドの最新の呼出しに指定されたブロッカ・オブジェクトを返します。ブロックされていない場合はnullを返します。 返される値は、瞬間的なスナップショットです。そのため、スレッドは別のブロッカ・オブジェクトでブロック解除されていることもブロックされていることもあります。
        パラメータ:
        t - スレッド
        戻り値:
        ブロッカ
        例外:
        NullPointerException - 引数がnullの場合
        導入されたバージョン:
        1.6
      • park

        public static void park()
        パーミットが利用可能でない場合、スレッドのスケジューリングに関して現在のスレッドを無効にします。

        パーミットが使用可能な場合、これは消費され、呼出しはただちに復帰します。それ以外の場合、現在のスレッドは、スレッド・スケジューリングに関して無効になり、次の3つのいずれかが起きるまで待機します。

        • ほかのスレッドが、現在のスレッドをターゲットとしてunparkを呼び出す。
        • ほかのスレッドが現在のスレッドに割り込みを行う。または
        • 呼出しが、見せかけで(理由もなく)復帰する。

        このメソッドは、これらのどれがメソッド復帰の原因となったかはレポートしません 呼出し側は、スレッドの初回parkの原因となった状態を再チェックする必要があります。 呼出し側は、復帰時のスレッドの割込み状態なども判定できます。

      • parkNanos

        public static void parkNanos​(long nanos)
        パーミットが利用可能である場合を除き、現在のスレッドを、指定された待機時間までスレッド・スケジューリングに関して無効にします。

        パーミットが使用可能な場合、これは消費され、呼出しはただちに復帰します。それ以外の場合、現在のスレッドは、スレッド・スケジューリングに関して無効になり、次の4つのいずれかが起きるまで待機します。

        • ほかのスレッドが、現在のスレッドをターゲットとしてunparkを呼び出す。
        • ほかのスレッドが現在のスレッドに割り込みを行う。または
        • 指定された待機時間が経過する。または
        • 呼出しが、見せかけで(理由もなく)復帰する。

        このメソッドは、これらのどれがメソッド復帰の原因となったかはレポートしません 呼出し側は、スレッドの初回parkの原因となった状態を再チェックする必要があります。 呼出し側は、スレッドの割込み状態や、復帰時の経過時間なども判定できます。

        パラメータ:
        nanos - 待機する最大ナノ秒数
      • parkUntil

        public static void parkUntil​(long deadline)
        パーミットが利用可能でない場合、指定された期限まで、スレッドのスケジューリングに関して現在のスレッドを無効にします。

        パーミットが使用可能な場合、これは消費され、呼出しはただちに復帰します。それ以外の場合、現在のスレッドは、スレッド・スケジューリングに関して無効になり、次の4つのいずれかが起きるまで待機します。

        • ほかのスレッドが、現在のスレッドをターゲットとしてunparkを呼び出す。
        • ほかのスレッドが現在のスレッドに割り込みを行う。または
        • 指定された期限が経過する。または
        • 呼出しが、見せかけで(理由もなく)復帰する。

        このメソッドは、これらのどれがメソッド復帰の原因となったかはレポートしません 呼出し側は、スレッドの初回parkの原因となった状態を再チェックする必要があります。 呼出し側は、スレッドの割込み状態や、復帰時の現在時刻なども判定できます。

        パラメータ:
        deadline - 待機用の、元期からのミリ秒単位の絶対時間