モジュール java.base

クラスStampedLock

  • すべての実装されたインタフェース:
    Serializable

    public class StampedLock
    extends Object
    implements Serializable
    読取り/書込みアクセスを制御する3つのモードを持つ機能ベースのロックです。 StampedLockの状態はバージョンとモードから構成されます。 ロック取得メソッドは、ロック状態に対するアクセスを表現および制御するスタンプを返します。これらのメソッドの「try」バージョンは、アクセスの取得失敗を表すために特殊な値ゼロを代わりに返す場合があります。 ロック解放メソッドとロック変換メソッドは、引数としてスタンプを必要とし、それらがロックの状態と一致しない場合は失敗します。 モードは次の3つです。
    • 書込み。 writeLock()メソッドは、排他的アクセスを待機してブロックする可能性があり、ロックを解放するためにunlockWrite(long)メソッドで使用できるスタンプを返します。 時間指定のないバージョンと時間指定のあるバージョンのtryWriteLockも用意されています。 ロックが書込みモードで保持されているときは、読取りロックを取得することはできず、オプティミスティック読取り検証はすべて失敗します。
    • 読取り。 readLock()メソッドは、非排他的アクセスを待機してブロックする可能性があり、ロックを解放するためにunlockRead(long)メソッドで使用できるスタンプを返します。 時間指定のないバージョンと時間指定のあるバージョンのtryReadLockも用意されています。
    • オプティミスティック読取り。 tryOptimisticRead()メソッドは、現在ロックが書込みモードで保持されていない場合のみ、ゼロ以外のスタンプを返します。 validate(long)メソッドは、指定されたスタンプの取得以降にロックが書込みモードで取得されていない場合、trueを返します。 このモードは、ライターがいつでも破ることのできる、きわめて弱い読取りロックと見なすことができます。 読取り専用の短いコード・セグメントにオプティミスティック・モードを使用すると、競合が減り、スループットが向上ことがよくあります。 ただし、その使用は本質的に脆弱です。 オプティミスティック読取りセクションでは、フィールドを読み取り、それらを後で検証してから使用するためにローカル変数に保持することだけを行うべきです。 オプティミスティック・モードでは、読み取られたフィールドが大きく矛盾している可能性があるため、一貫性をチェックしたりvalidate()メソッドを繰り返し呼び出したりするためのデータ表現に十分習熟している場合にかぎり使用できます。 たとえば、最初にオブジェクト参照または配列参照を読み取り、次にそのフィールド、要素、またはメソッドの1つにアクセスする場合、通常そのようなステップが必要になります。

    このクラスは、条件に応じて3つのモード間の変換を提供するメソッドもサポートしています。 たとえば、tryConvertToWriteLock(long)メソッドはモードの「アップグレード」を試み、(1)すでに書込みモードの場合、(2)読取りモードで他にリーダーがない場合、または(3)オプティミスティック・モードでロックが使用可能な場合は、有効な書込みスタンプを返します。 これらのメソッドの形式は、再試行ベースの設計で発生するコードの膨張をいくから軽減できるように設計されています。

    StampedLockは、スレッドセーフなコンポーネントの開発で内部ユーティリティとして使用するために設計されています。 これらを使用するには、保護するデータ、オブジェクト、およびメソッドの内部プロパティの知識が必要です。 これらは再入可能ではないため、ロックされている本体では、ロックの再取得を試みる可能性のある他の不明なメソッドを呼び出すべきではありません(ただし、スタンプを使用または変換できる他のメソッドにスタンプを渡すことはできます)。 読取りロック・モードを使用するには、関連するコード・セクションが副作用を持っていないことが必要です。 未検証のオプティミスティック読取りセクションでは、潜在的な不整合を許容できることがわかっていないメソッドを呼び出すことはできません。 スタンプは有限表示を使用し、暗号的にセキュアではありません(つまり、有効なスタンプが推測可能な場合があります)。 スタンプの値は、1年以上の連続動作の後で再循環する場合があります。 これより長い期間、使用も検証もされずに保持されたスタンプは、正しく検証できない場合があります。 StampedLockは直列化可能ですが、常に初期のロック解除された状態に直列化復元されるため、リモート・ロックには役立ちません。

    Semaphoreのように、ほとんどのLock実装とは異なり、StampedLocksには所有権の概念はありません。 あるスレッドで取得されたロックは、別のスレッドで解放または変換できます。

    StampedLockのスケジューリング・ポリシーでは、リーダーとライターのどちらを優先するかに一貫性がありません。 「try」メソッドはすべてベスト・エフォート型であり、スケジューリング・ポリシーや公平性ポリシーに必ずしも準拠していません。 ロックを取得または変換する「try」メソッドからゼロが返された場合、ロックの状態に関する情報は提供されません。それ以降の呼び出しが成功する場合もあります。

    このクラスでは、複数のロック・モードを調整する使用方法がサポートされているため、LockインタフェースやReadWriteLockインタフェースは直接実装されません。 ただし、関連する機能セットだけを必要とするアプリケーションでは、StampedLockがasReadLock()asWriteLock()、またはasReadWriteLock()と見なされることもあります。

    使用例。 単純な2次元の点を保持するクラスにおけるいくつかの使用方法を次に示します。 サンプル・コードにはいくつかのtry/catch技法が示されていますが、その本体で例外が発生する可能性はないため、ここではこれらが厳密に必要なわけではありません。

     
     class Point {
       private double x, y;
       private final StampedLock sl = new StampedLock();
    
       // an exclusively locked method
       void move(double deltaX, double deltaY) {
         long stamp = sl.writeLock();
         try {
           x += deltaX;
           y += deltaY;
         } finally {
           sl.unlockWrite(stamp);
         }
       }
    
       // a read-only method
       // upgrade from optimistic read to read lock
       double distanceFromOrigin() {
         long stamp = sl.tryOptimisticRead();
         try {
           retryHoldingLock: for (;; stamp = sl.readLock()) {
             if (stamp == 0L)
               continue retryHoldingLock;
             // possibly racy reads
             double currentX = x;
             double currentY = y;
             if (!sl.validate(stamp))
               continue retryHoldingLock;
             return Math.hypot(currentX, currentY);
           }
         } finally {
           if (StampedLock.isReadLockStamp(stamp))
             sl.unlockRead(stamp);
         }
       }
    
       // upgrade from optimistic read to write lock
       void moveIfAtOrigin(double newX, double newY) {
         long stamp = sl.tryOptimisticRead();
         try {
           retryHoldingLock: for (;; stamp = sl.writeLock()) {
             if (stamp == 0L)
               continue retryHoldingLock;
             // possibly racy reads
             double currentX = x;
             double currentY = y;
             if (!sl.validate(stamp))
               continue retryHoldingLock;
             if (currentX != 0.0 || currentY != 0.0)
               break;
             stamp = sl.tryConvertToWriteLock(stamp);
             if (stamp == 0L)
               continue retryHoldingLock;
             // exclusive access
             x = newX;
             y = newY;
             return;
           }
         } finally {
           if (StampedLock.isWriteLockStamp(stamp))
             sl.unlockWrite(stamp);
         }
       }
    
       // Upgrade read lock to write lock
       void moveIfAtOrigin(double newX, double newY) {
         long stamp = sl.readLock();
         try {
           while (x == 0.0 && y == 0.0) {
             long ws = sl.tryConvertToWriteLock(stamp);
             if (ws != 0L) {
               stamp = ws;
               x = newX;
               y = newY;
               break;
             }
             else {
               sl.unlockRead(stamp);
               stamp = sl.writeLock();
             }
           }
         } finally {
           sl.unlock(stamp);
         }
       }
     }

    導入されたバージョン:
    1.8
    関連項目:
    直列化された形式
    • コンストラクタのサマリー

      コンストラクタ 
      コンストラクタ 説明
      StampedLock()
      新しいロックを、最初はロック解除された状態で作成します。
    • メソッドのサマリー

      すべてのメソッド 静的メソッド インスタンス・メソッド 具象メソッド 
      修飾子と型 メソッド 説明
      Lock asReadLock()
      このStampedLockのプレーンなLockビューを返します。そこでは、Lock.lock()メソッドがreadLock()にマップされ、他のメソッドも同様にマップされます。
      ReadWriteLock asReadWriteLock()
      このStampedLockのReadWriteLockビューを返します。そこでは、ReadWriteLock.readLock()メソッドがasReadLock()にマップされ、ReadWriteLock.writeLock()asWriteLock()にマップされます。
      Lock asWriteLock()
      このStampedLockのプレーンなLockビューを返します。そこでは、Lock.lock()メソッドがwriteLock()にマップされ、他のメソッドも同様にマップされます。
      int getReadLockCount()
      このロック用に保持されている読込みロックの数を照会します。
      static boolean isLockStamp​(long stamp)
      スタンプがロックを保持しているかどうかを示します。
      static boolean isOptimisticReadStamp​(long stamp)
      スタンプが楽観的な読書が成功したかどうかを示します。
      boolean isReadLocked()
      現在ロックが非排他的に保持されている場合はtrueを返します。
      static boolean isReadLockStamp​(long stamp)
      スタンプが非排他的にロックを保持しているかどうかを示します。
      boolean isWriteLocked()
      現在ロックが排他的に保持されている場合はtrueを返します。
      static boolean isWriteLockStamp​(long stamp)
      スタンプが排他的にロックを保持しているかどうかを示します。
      long readLock()
      ロックを非排他的に取得し、利用可能になるまで必要に応じてブロックします。
      long readLockInterruptibly()
      ロックを非排他的に取得し、利用可能になるまで、または現在のスレッドが割り込まれるまで、必要に応じてブロックします。
      String toString()
      このロックおよびその状態を識別する文字列を返します。
      long tryConvertToOptimisticRead​(long stamp)
      ロック状態が指定されたスタンプと一致する場合、原子的に、スタンプがロックを保持していることを表す場合は、それを解放して観測スタンプを返します。
      long tryConvertToReadLock​(long stamp)
      ロック状態が指定されたスタンプと一致する場合、以下のアクションのいずれかを原子的に実行します。
      long tryConvertToWriteLock​(long stamp)
      ロック状態が指定されたスタンプと一致する場合、以下のアクションのいずれかを原子的に実行します。
      long tryOptimisticRead()
      後で検証できるスタンプを返します。排他的にロックされている場合はゼロを返します。
      long tryReadLock()
      ロックがすぐに利用できる場合に、それを非排他的に取得します。
      long tryReadLock​(long time, TimeUnit unit)
      指定された時間内でロックが利用可能になり、現在のスレッドで割込みが発生していない場合に、それを非排他的に取得します。
      boolean tryUnlockRead()
      読取りロックが保持される場合に、スタンプ値を必要としないで、その保持を解除します。
      boolean tryUnlockWrite()
      書込みロックが保持される場合に、スタンプ値を必要としないで、それを解除します。
      long tryWriteLock()
      ロックがすぐに利用できる場合に、それを排他的に取得します。
      long tryWriteLock​(long time, TimeUnit unit)
      指定された時間内でロックが利用可能になり、現在のスレッドで割込みが発生していない場合に、それを排他的に取得します。
      void unlock​(long stamp)
      ロック状態が指定されたスタンプと一致する場合に、対応するロック・モードを解除します。
      void unlockRead​(long stamp)
      ロック状態が指定されたスタンプと一致する場合に、非排他ロックを解除します。
      void unlockWrite​(long stamp)
      ロック状態が指定されたスタンプと一致する場合に、排他ロックを解除します。
      boolean validate​(long stamp)
      指定されたスタンプの発行以降にロックが排他的に取得されなかった場合にtrueを返します。
      long writeLock()
      ロックを排他的に取得し、必要に応じて利用可能になるまでブロックします。
      long writeLockInterruptibly()
      ロックを排他的に取得し、必要に応じて利用可能になるか、現在のスレッドで割込みが発生するまでブロックします。
    • コンストラクタの詳細

      • StampedLock

        public StampedLock()
        新しいロックを、最初はロック解除された状態で作成します。
    • メソッドの詳細

      • writeLock

        public long writeLock()
        ロックを排他的に取得し、必要に応じて利用可能になるまでブロックします。
        戻り値:
        モードを解除または変換するために使用できる書き込みスタンプ
      • tryWriteLock

        public long tryWriteLock()
        ロックがすぐに利用できる場合に、それを排他的に取得します。
        戻り値:
        ロック解除または変換モードに使用できる書き込みスタンプ、またはロックが使用できない場合はゼロ
      • tryWriteLock

        public long tryWriteLock​(long time,
                                 TimeUnit unit)
                          throws InterruptedException
        指定された時間内でロックが利用可能になり、現在のスレッドで割込みが発生していない場合に、それを排他的に取得します。 タイムアウト時および割込み時の動作は、Lock.tryLock(long,TimeUnit)メソッドに指定されているものと同じです。
        パラメータ:
        time - ロックの最長待機時間
        unit - time引数の時間単位
        戻り値:
        ロック解除または変換モードに使用できる書き込みスタンプ、またはロックが使用できない場合はゼロ
        例外:
        InterruptedException - ロックを取得する前に現在のスレッドで割込みが発生した場合
      • writeLockInterruptibly

        public long writeLockInterruptibly()
                                    throws InterruptedException
        ロックを排他的に取得し、必要に応じて利用可能になるか、現在のスレッドで割込みが発生するまでブロックします。 割込み時の動作は、Lock.lockInterruptibly()メソッドに指定されているものと同じです。
        戻り値:
        モードを解除または変換するために使用できる書き込みスタンプ
        例外:
        InterruptedException - ロックを取得する前に現在のスレッドで割込みが発生した場合
      • readLock

        public long readLock()
        ロックを非排他的に取得し、利用可能になるまで必要に応じてブロックします。
        戻り値:
        モードを解除または変換するために使用できる読み取りスタンプ
      • tryReadLock

        public long tryReadLock()
        ロックがすぐに利用できる場合に、それを非排他的に取得します。
        戻り値:
        モードのロック解除または変換に使用できる読み取りスタンプ、またはロックが使用できない場合はゼロ
      • tryReadLock

        public long tryReadLock​(long time,
                                TimeUnit unit)
                         throws InterruptedException
        指定された時間内でロックが利用可能になり、現在のスレッドで割込みが発生していない場合に、それを非排他的に取得します。 タイムアウト時および割込み時の動作は、Lock.tryLock(long,TimeUnit)メソッドに指定されているものと同じです。
        パラメータ:
        time - ロックの最長待機時間
        unit - time引数の時間単位
        戻り値:
        モードのロック解除または変換に使用できる読み取りスタンプ、またはロックが使用できない場合はゼロ
        例外:
        InterruptedException - ロックを取得する前に現在のスレッドで割込みが発生した場合
      • readLockInterruptibly

        public long readLockInterruptibly()
                                   throws InterruptedException
        ロックを非排他的に取得し、利用可能になるまで、または現在のスレッドが割り込まれるまで、必要に応じてブロックします。 割込み時の動作は、Lock.lockInterruptibly()メソッドに指定されているものと同じです。
        戻り値:
        モードを解除または変換するために使用できる読み取りスタンプ
        例外:
        InterruptedException - ロックを取得する前に現在のスレッドで割込みが発生した場合
      • tryOptimisticRead

        public long tryOptimisticRead()
        後で検証できるスタンプを返します。排他的にロックされている場合はゼロを返します。
        戻り値:
        有効な楽観的な読み取りスタンプ、または排他的にロックされている場合はゼロ
      • validate

        public boolean validate​(long stamp)
        指定されたスタンプの発行以降にロックが排他的に取得されなかった場合にtrueを返します。 スタンプがゼロの場合は常にfalseを返します。 スタンプが現在保持されているロックを表している場合は、常にtrueを返します。 tryOptimisticRead()またはこのロックのロック・メソッドから取得されたものではない値を指定してこのメソッドを呼び出した場合、その効果や結果は定義されていません。
        パラメータ:
        stamp - スタンプ
        戻り値:
        指定されたスタンプの発行以降にロックが排他的に取得されていない場合はtrue、それ以外の場合はfalse
      • unlockWrite

        public void unlockWrite​(long stamp)
        ロック状態が指定されたスタンプと一致する場合に、排他ロックを解除します。
        パラメータ:
        stamp - 書込みロック操作によって返されたスタンプ
        例外:
        IllegalMonitorStateException - スタンプがこのロックの現在の状態と一致しない場合
      • unlockRead

        public void unlockRead​(long stamp)
        ロック状態が指定されたスタンプと一致する場合に、非排他ロックを解除します。
        パラメータ:
        stamp - 読取りロック操作によって返されたスタンプ
        例外:
        IllegalMonitorStateException - スタンプがこのロックの現在の状態と一致しない場合
      • unlock

        public void unlock​(long stamp)
        ロック状態が指定されたスタンプと一致する場合に、対応するロック・モードを解除します。
        パラメータ:
        stamp - ロック操作によって返されたスタンプ
        例外:
        IllegalMonitorStateException - スタンプがこのロックの現在の状態と一致しない場合
      • tryConvertToWriteLock

        public long tryConvertToWriteLock​(long stamp)
        ロック状態が指定されたスタンプと一致する場合、以下のアクションのいずれかを原子的に実行します。 スタンプが書込みロックの保持を表している場合は、それを返します。 読取りロックであれば、書込みロックが使用可能な場合は読取りロックを解放し、書込みスタンプを返します。 オプティミスティック読取りであれば、すぐに利用できる場合のみ書込みスタンプを返します。 このメソッドは、その他の場合はすべてゼロを返します。
        パラメータ:
        stamp - スタンプ
        戻り値:
        有効な書込みスタンプ。失敗した場合はゼロ
      • tryConvertToReadLock

        public long tryConvertToReadLock​(long stamp)
        ロック状態が指定されたスタンプと一致する場合、以下のアクションのいずれかを原子的に実行します。 スタンプが書込みロックの保持を表している場合は、それを解放し、読取りロックを取得します。 読取りロックであれば、それを返します。 オプティミスティック読取りであれば、すぐに利用できる場合のみ読取りロックを取得し、読取りスタンプを返します。 このメソッドは、その他の場合はすべてゼロを返します。
        パラメータ:
        stamp - スタンプ
        戻り値:
        有効な読取りスタンプ。失敗した場合はゼロ
      • tryConvertToOptimisticRead

        public long tryConvertToOptimisticRead​(long stamp)
        ロック状態が指定されたスタンプと一致する場合、原子的に、スタンプがロックを保持していることを表す場合は、それを解放して観測スタンプを返します。 オプティミスティック読取りであれば、検証されている場合はそれを返します。 このメソッドは、その他の場合はすべてゼロを返すため、「tryUnlock」の一種として役立つ場合があります。
        パラメータ:
        stamp - スタンプ
        戻り値:
        有効なオプティミスティック読取りスタンプ。失敗した場合はゼロ
      • tryUnlockWrite

        public boolean tryUnlockWrite()
        書込みロックが保持される場合に、スタンプ値を必要としないで、それを解除します。 このメソッドは、エラー後の回復に役立つ場合があります。
        戻り値:
        ロックが保持されていた場合はtrue。それ以外の場合はfalse
      • tryUnlockRead

        public boolean tryUnlockRead()
        読取りロックが保持される場合に、スタンプ値を必要としないで、その保持を解除します。 このメソッドは、エラー後の回復に役立つ場合があります。
        戻り値:
        読取りロックが保持されていた場合はtrue。それ以外の場合はfalse
      • isWriteLocked

        public boolean isWriteLocked()
        現在ロックが排他的に保持されている場合はtrueを返します。
        戻り値:
        現在ロックが排他的に保持されている場合はtrue
      • isReadLocked

        public boolean isReadLocked()
        現在ロックが非排他的に保持されている場合はtrueを返します。
        戻り値:
        現在ロックが非排他的に保持されている場合はtrue
      • isWriteLockStamp

        public static boolean isWriteLockStamp​(long stamp)
        スタンプが排他的にロックを保持しているかどうかを示します。 このメソッドは、tryConvertToWriteLock(long)と組み合わせて使用すると便利です。例:
         
         long stamp = sl.tryOptimisticRead();
         try {
           ...
           stamp = sl.tryConvertToWriteLock(stamp);
           ...
         } finally {
           if (StampedLock.isWriteLockStamp(stamp))
             sl.unlockWrite(stamp);
         }
        パラメータ:
        stamp - 以前のStampedLock操作によって返されたスタンプ
        戻り値:
        trueスタンプが正常な書き込みロック操作によって戻された場合
        導入されたバージョン:
        10
      • isReadLockStamp

        public static boolean isReadLockStamp​(long stamp)
        スタンプが非排他的にロックを保持しているかどうかを示します。 このメソッドは、tryConvertToReadLock(long)と組み合わせて使用すると便利です。例:
         
         long stamp = sl.tryOptimisticRead();
         try {
           ...
           stamp = sl.tryConvertToReadLock(stamp);
           ...
         } finally {
           if (StampedLock.isReadLockStamp(stamp))
             sl.unlockRead(stamp);
         }
        パラメータ:
        stamp - 以前のStampedLock操作によって返されたスタンプ
        戻り値:
        成功した読み取りロック操作によってスタンプが戻された場合はtrue
        導入されたバージョン:
        10
      • isLockStamp

        public static boolean isLockStamp​(long stamp)
        スタンプがロックを保持しているかどうかを示します。 このメソッドは、tryConvertToReadLock(long)およびtryConvertToWriteLock(long)と一緒に使用すると便利です。たとえば、次のようになります:
         
         long stamp = sl.tryOptimisticRead();
         try {
           ...
           stamp = sl.tryConvertToReadLock(stamp);
           ...
           stamp = sl.tryConvertToWriteLock(stamp);
           ...
         } finally {
           if (StampedLock.isLockStamp(stamp))
             sl.unlock(stamp);
         }
        パラメータ:
        stamp - 以前のStampedLock操作によって返されたスタンプ
        戻り値:
        成功した読み取りロックまたは書き込みロック操作によってスタンプが戻された場合はtrue
        導入されたバージョン:
        10
      • isOptimisticReadStamp

        public static boolean isOptimisticReadStamp​(long stamp)
        スタンプが楽観的な読書が成功したかどうかを示します。
        パラメータ:
        stamp - 以前のStampedLock操作によって返されたスタンプ
        戻り値:
        true tryOptimisticRead()またはtryConvertToOptimisticRead(long)からの非ゼロ戻りの正常な読み取り操作によってスタンプが戻された場合
        導入されたバージョン:
        10
      • getReadLockCount

        public int getReadLockCount()
        このロック用に保持されている読込みロックの数を照会します。 このメソッドは、同期の制御用としてではなく、システム状態の監視用として設計されています。
        戻り値:
        保持する読込みロックの数
      • toString

        public String toString()
        このロックおよびその状態を識別する文字列を返します。 状態は括弧で囲まれ、文字列 "Unlocked"または文字列"Write-locked"または文字列"Read-locks:"に続いて、現在保持されている読取りロックの数が含まれます。
        オーバーライド:
        toString、クラスObject
        戻り値:
        このロックおよびその状態を識別する文字列
      • asReadLock

        public Lock asReadLock()
        このStampedLockのプレーンなLockビューを返します。そこでは、Lock.lock()メソッドがreadLock()にマップされ、他のメソッドも同様にマップされます。 返されたLockはConditionをサポートしていないため、Lock.newCondition()メソッドはUnsupportedOperationExceptionをスローします。
        戻り値:
        ロック
      • asWriteLock

        public Lock asWriteLock()
        このStampedLockのプレーンなLockビューを返します。そこでは、Lock.lock()メソッドがwriteLock()にマップされ、他のメソッドも同様にマップされます。 返されたLockはConditionをサポートしていないため、Lock.newCondition()メソッドはUnsupportedOperationExceptionをスローします。
        戻り値:
        ロック