クラスStampedLock
- すべての実装されたインタフェース:
Serializable
- 書込み。
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 booleanisLockStamp(long stamp) スタンプがロックを保持しているかどうかを示します。static booleanisOptimisticReadStamp(long stamp) スタンプが楽観的な読書が成功したかどうかを示します。boolean現在ロックが非排他的に保持されている場合はtrueを返します。static booleanisReadLockStamp(long stamp) スタンプが非排他的にロックを保持しているかどうかを示します。boolean現在ロックが排他的に保持されている場合はtrueを返します。static booleanisWriteLockStamp(long stamp) スタンプが排他的にロックを保持しているかどうかを示します。longreadLock()ロックを非排他的に取得し、利用可能になるまで必要に応じてブロックします。longロックを非排他的に取得し、利用可能になるまで、または現在のスレッドが割り込まれるまで、必要に応じてブロックします。toString()このロックおよびその状態を識別する文字列を返します。longtryConvertToOptimisticRead(long stamp) ロック状態が指定されたスタンプと一致する場合、スタンプがロックを保持していることを表す場合は、そのスタンプを解放し、監視スタンプを返します。longtryConvertToReadLock(long stamp) ロック状態が指定されたスタンプと一致する場合、次のアクションのいずれかを原子的に実行します。longtryConvertToWriteLock(long stamp) ロック状態が指定されたスタンプと一致する場合、次のアクションのいずれかを原子的に実行します。long後で検証できるスタンプを返します。排他的にロックされている場合はゼロを返します。longロックがすぐに利用できる場合に、それを非排他的に取得します。longtryReadLock(long time, TimeUnit unit) 指定された時間内でロックが利用可能になり、現在のスレッドで割込みが発生していない場合に、それを非排他的に取得します。boolean読取りロックが保持される場合に、スタンプ値を必要としないで、その保持を解除します。boolean書込みロックが保持される場合に、スタンプ値を必要としないで、それを解除します。longロックがすぐに利用できる場合に、それを排他的に取得します。longtryWriteLock(long time, TimeUnit unit) 指定された時間内でロックが利用可能になり、現在のスレッドで割込みが発生していない場合に、それを排他的に取得します。voidunlock(long stamp) ロック状態が指定されたスタンプと一致する場合に、対応するロック・モードを解除します。voidunlockRead(long stamp) ロック状態が指定されたスタンプと一致する場合に、非排他ロックを解除します。voidunlockWrite(long stamp) ロック状態が指定されたスタンプと一致する場合に、排他ロックを解除します。booleanvalidate(long stamp) 指定されたスタンプの発行以降にロックが排他的に取得されなかった場合にtrueを返します。longロックを排他的に取得し、必要に応じて利用可能になるまでブロックします。longロックを排他的に取得し、必要に応じて利用可能になるか、現在のスレッドで割込みが発生するまでブロックします。
-
コンストラクタの詳細
-
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操作によって返されたスタンプ- 戻り値:
truetryOptimisticRead()またはtryConvertToOptimisticRead(long)からの非ゼロ戻りの正常な読み取り操作によってスタンプが戻された場合- 導入されたバージョン:
- 10
-
getReadLockCount
public int getReadLockCount()このロック用に保持されている読込みロックの数を照会します。 このメソッドは、同期の制御用としてではなく、システム状態の監視用として設計されています。- 戻り値:
- 保持する読込みロックの数
-
toString
-
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()にマップされます。- 戻り値:
- ロック
-