クラスStampedLock

java.lang.Object
java.util.concurrent.locks.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を返します。この 合、tryOptimisticReadへの呼び出しのあとに、最新の書き込みロック・リリースより前のすべてのアクションが発生します。 このモードは、ライターがいつでも ることのできる、きわめて弱い読取りロックと見なすことができます。 短い読取り専用コード・セグメントにはオプティミスティック読取りモードを使用することで、競合が減少し、スループットが向上することがよくあります。 た し、その使用は本質的に脆弱です。 オプティミスティック読取りセクションでは、フィールドを読み取り、それらを後で検証してから使用するためにローカル変数に保持すること けを行うべきです。 オプティミスティック読取りモードでは読取りフィールドに一貫性がない 合があるため、データ表現を十分に理解していて一貫性をチェックしたり、メソッドvalidate()を繰り返し呼び出す 合にのみ使用方法が適用されます。 たとえば、最初にオブジェクト参照または配列参照を読み取り、次にそのフィールド、要 、またはメソッドの1つにアクセスする 合、通常そのようなステップが必要になります。

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

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

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

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

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

メモリーの同期化 正常にロックされた 合のいずれかのモードへの影響を及ぼすメソッドのメモリー同期は、「Java言語仕様」の第17  で説明しているように、「ロック」アクションと同じ効果を持ちます。 書込みモードでメソッドのロックを正常に解除すると、メモリー同期の結果は「ロック解除」アクションと同じになります。 オプティミスティック読取りの使用方法では、最新の書込みモードのロック解除アクションより前のアクションは、将来の検証でtrueが戻された 合にのみ、tryOptimisticReadの後続のアクションが発生することが保証されています。そうでない 合、tryOptimisticRead間の読取りと一貫性のあるスナップショットの取得は保証されません。

使用例 単純な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 moveIfAtOrigin2(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);
     }
   }
 }

Java言語仕様を参照してく さい:
17.4 メモリー・モデル
導入されたバージョン:
1.8
関連 目:
  • コンストラクタのサマリー

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

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

    クラスjava.lang.Objectで宣言されたメソッド

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
  • コンストラクタの詳細

    • 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をスローします。
      戻り値:
      ロック
    • asReadWriteLock

      public ReadWriteLock asReadWriteLock()
      このStampedLockのReadWriteLockビューを返します。そこでは、ReadWriteLock.readLock()メソッドがasReadLock()にマップされ、ReadWriteLock.writeLock()asWriteLock()にマップされます。
      戻り値:
      ロック