|
JavaTM Platform Standard Ed. 6 |
|||||||||
| 前のクラス 次のクラス | フレームあり フレームなし | |||||||||
| 概要: 入れ子 | フィールド | コンストラクタ | メソッド | 詳細: フィールド | コンストラクタ | メソッド | |||||||||
public interface Lock
Lock 実装は、synchronized のメソッドや文を使用することで取得可能なロック操作よりも広範なロック操作を提供します。この実装を使用すると、より柔軟な構造やまったく異なるプロパティーを保持したり、関連する複数の Condition オブジェクトをサポートできるようになります。
ロックは、複数のスレッドによる共有リソースへのアクセスを制御するためのツールです。通常、ロックは共有リソースへの排他的なアクセスを提供します。ロックを取得できるのは一度に 1 つのスレッドだけであり、すべての共有リソースにアクセスするにはロックを最初に取得する必要があります。ただし、ReadWriteLock の読み込みロックなどの一部のロックでは、共有リソースへの並行アクセスが許可される場合があります。
synchronized メソッドや文の使用により、各オブジェクトに関連付けられた暗黙の監視ロックへのアクセスを提供できますが、ロックの取得および解放はすべてブロック構造に従って行うことが求められます。このため、複数のロックが取得された場合、その解放は取得とは反対の順序で行う必要があります。また、すべてのロックの解放は、それらが取得された範囲内で行う必要があります。
synchronized メソッドおよび文の範囲機構は、監視ロックのプログラミングを大幅に容易にするとともに、ロックに関連した一般的なプログラミングエラーの多くを避けるのに役立ちますが、ロックの操作をより柔軟に行う必要のある状況が存在します。たとえば、データ構造に並行してアクセスする一部のトラバーサルアルゴリズムでは、「hand-over-hand」または「chain locking」を使用する必要があります。この場合、ノード A のロックを取得し、次にノード B のロックを取得し、次に A を解放して C を取得し、次に B を解放して D を取得する、という具合に処理を進めます。Lock インタフェースを実装すると、異なるスコープ内でロックを取得および解放したり、複数のロックを任意の順序で取得および解放することが可能になるため、この種のテクニックを利用できるようになります。
このように柔軟性が高まると、新たな責任も発生します。ブロック構造ロックが存在しなくなることで、synchronized メソッドおよび文で実行されるロックの自動解放が機能しなくなります。たいていの場合、次のコードを使用する必要があります。
Lock l = ...;
l.lock();
try {
// access the resource protected by this lock
} finally {
l.unlock();
}
ロックおよびロック解除が異なるスコープ内で行われる場合、ロックの保持中に実行されるすべてのコードが try-finally または try-catch により保護され、必要に応じてロックが確実に解放されるように注意を払う必要があります。
Lock 実装は、ロック (tryLock()) を取得するための非ブロック試行、割り込み可能なロック (lockInterruptibly() やタイムアウト可能なロック (tryLock(long, TimeUnit)) を取得する試行を提供することにより、synchronized メソッドおよび文への追加機能を提供します。
Lock クラスは、保証された順序付け、再入不可能な使用、デッドロックの検出など、暗黙の監視ロックとはまったく異なる動作やセマンティクスを提供できます。実装がこうした特殊セマンティクスを提供する場合、実装はこれらのセマンティクスをドキュメント化する必要があります。
Lock インスタンスは通常のオブジェクトに過ぎず、それ自体を synchronized 文のターゲットとして使用できることに留意してください。Lock インスタンスの監視ロックを取得することと、そのインスタンスのいずれかの lock() メソッドを呼び出すこととは、特に関係がありません。混乱を避けるため、独自の実装以外では、このような方法で Lock インスタンスを決して使用しないことをお勧めします。
特に明記されていないかぎり、いずれかのパラメータに対し null 値を渡すと、NullPointerException がスローされます。
すべての Lock 実装は、『Java 言語仕様第 3 版 (17.4 メモリーモデル)』に記述されているように、組み込み監視ロックが提供するのと同じメモリー同期セマンティクスを施行する必要があります。
lock 操作は、成功する Lock アクションと同様のメモリー同期効果がある。
unlock 操作は、成功する Unlock アクションと同様のメモリー同期効果がある。
ロック取得の 3 つの形式 (割り込み可、割り込み不可、および時刻指定) では、パフォーマンス特性、順序付けの保証、ほかの実装品質が異なります。また、「進行中の」ロック取得への割り込み機能も、指定された Lock クラスでは使用できません。このため、3 つのロック取得形式すべてで、実装が厳密に同じ保証やセマンティクスを定義する必要はありません。また、進行中のロック取得の割り込みをサポートする必要もありません。実装は、各ロックメソッドの提供するセマンティクスおよび保証を明確にドキュメント化する必要があります。また、ロック取得の割り込みがサポートされる範囲内 (全体またはメソッドエントリのみ) で、このインタフェースで定義された割り込みセマンティクスに従う必要もあります。
通常、割り込みは取り消しを意味し、割り込みのチェックは頻繁に行われるものではないため、実装は通常のメソッド復帰に対する割り込みに肯定的に応答できます。これは、別のアクションがスレッドをブロック解除したあとに、割り込みが発生したことが示される場合にも当てはまります。実装は、この動作をドキュメント化する必要があります。
ReentrantLock,
Condition,
ReadWriteLock| メソッドの概要 | |
|---|---|
void |
lock()
ロックを取得します。 |
void |
lockInterruptibly()
現在のスレッドが interrupted でないかぎり、ロックを取得します。 |
Condition |
newCondition()
この Lock インスタンスにバインドされた新規 Condition を返します。 |
boolean |
tryLock()
呼び出し時にロックされていない場合にのみ、ロックを取得します。 |
boolean |
tryLock(long time,
TimeUnit unit)
指定された待機時間内でロックが利用可能であり、現在のスレッドで割り込みが発生していない場合に、ロックを取得します。 |
void |
unlock()
このロックを解除します。 |
| メソッドの詳細 |
|---|
void lock()
ロックを使用できない場合、現在のスレッドはスレッドのスケジューリングに関して無効になり、ロックが取得されるまで待機します。
実装上の考慮事項
Lock 実装は、デッドロックを引き起こす呼び出しなどのロックの不正使用を検出し、そのような状況で (チェックされない) 例外をスローできます。Lock 実装により、該当する状況および例外の型をドキュメント化する必要があります。
void lockInterruptibly()
throws InterruptedException
利用可能な場合にロックを取得して、すぐに復帰します。
ロックを使用できない場合、現在のスレッドはスレッドのスケジューリングに関して無効になり、次の 2 つのいずれかが起きるまで待機します。
現在のスレッドで、
InterruptedException がスローされ、現在のスレッドの割り込みステータスがクリアされます。
実装上の考慮事項
ある状況下ではロック取得に割り込むことができず、場合によっては負荷の大きい操作になる場合があります。プログラマは、このような場合があることを意識しておく必要があります。実装は、該当する状況をドキュメント化する必要があります。
実装は、通常のメソッド復帰に対する割り込みに肯定的に応答できます。
Lock 実装は、デッドロックを引き起こす呼び出しなどのロックの不正使用を検出し、そのような状況で (チェックされない) 例外をスローできます。Lock 実装により、該当する状況および例外の型をドキュメント化する必要があります。
InterruptedException - ロックの取得中 (およびロック取得の中断がサポートされている状況) に、現在のスレッドで割り込みが発生する場合boolean tryLock()
可能な場合にロックを取得し、値 true ですぐに復帰します。ロックが利用可能でない場合、このメソッドは値 false ですぐに復帰します。
このメソッドの通常の使用方法を次に示します。
Lock lock = ...;
if (lock.tryLock()) {
try {
// manipulate protected state
} finally {
lock.unlock();
}
} else {
// perform alternative actions
}
この使用により、ロックが取得された場合にロックが解除されること、およびロックが取得されなかった場合にロック解除を試みないことが保証されます。
true、そうでない場合は false
boolean tryLock(long time,
TimeUnit unit)
throws InterruptedException
ロックが利用可能な場合、このメソッドはただちに値 true で復帰します。ロックが利用できない場合、現在のスレッドがスレッドスケジューリングに関して無効になり、次の 3 つのいずれかが起きるまで待機します。
ロックが取得されると、true が返されます。
現在のスレッドで、
InterruptedException がスローされ、現在のスレッドの割り込みステータスがクリアされます。
指定された待機時間が経過すると、値 false が返されます。時間がゼロまたはそれより小さい場合、メソッドは待機しません。
実装上の考慮事項
ある状況下ではロック取得に割り込むことができず、場合によっては負荷の大きい操作になる場合があります。プログラマは、このような場合があることを意識しておく必要があります。実装は、該当する状況をドキュメント化する必要があります。
実装は、通常のメソッド復帰に対する割り込み、またはタイムアウトのレポートに肯定的に応答できます。
Lock 実装は、デッドロックを引き起こす呼び出しなどのロックの不正使用を検出し、そのような状況で (チェックされない) 例外をスローできます。Lock 実装により、該当する状況および例外の型をドキュメント化する必要があります。
time - ロックの最長待機時間unit - time 引数の時間単位
true、ロックが取得される前に待機時間が経過した場合は false
InterruptedException - ロックの取得中 (およびロック取得の中断がサポートされている状況) に、現在のスレッドで割り込みが発生する場合void unlock()
実装上の考慮事項
通常、Lock 実装は、ロックを解放可能なスレッドに関して制限を課し (一般に、ロックのホルダーだけが解放できる)、制限が侵された場合には (チェックされない) 例外をスローできます。Lock 実装により、制限および例外の型をドキュメント化する必要があります。
Condition newCondition()
Lock インスタンスにバインドされた新規 Condition を返します。
状態の待機を実行する前に、現在のスレッドがロックを保持する必要があります。Condition.await() への呼び出しにより、待機が復帰する前にロックを待機および再取得する前に、ロックが原子的に解放されます。
実装上の考慮事項
Condition インスタンスの厳密な操作は Lock 実装に依存するため、実装によりドキュメント化する必要があります。
Lock インスタンス用の新規 Condition
UnsupportedOperationException - この Lock 実装が状態をサポートしない場合
|
JavaTM Platform Standard Ed. 6 |
|||||||||
| 前のクラス 次のクラス | フレームあり フレームなし | |||||||||
| 概要: 入れ子 | フィールド | コンストラクタ | メソッド | 詳細: フィールド | コンストラクタ | メソッド | |||||||||
Copyright 2009 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. Documentation Redistribution Policy も参照してください。