public class ReentrantReadWriteLock extends Object implements ReadWriteLock, Serializable
ReentrantLock
と同様のセマンティクスをサポートする ReadWriteLock
の実装です。
このクラスには次の特性があります。
このクラスは、ロックアクセスに対するリーダーまたはライターの優先順序を規定しません。ただし、オプションの公平性ポリシーをサポートします。
書き込みロックが保持されている場合や待機中のライタースレッドが存在する場合、公平読み込みロック (再入不可能) を取得しようとするスレッドはブロックされます。そのようなスレッドは、現在待機中のライタースレッドのうちもっとも古いスレッドが書き込みロックを取得して解放するまで、読み込みロックを取得しません。もちろん、待機中のライターが待機を中止し、キュー内でもっとも長く待機している 1 つ以上のリーダースレッドに書き込みロックがかかっていない場合は、それらのリーダーに読み込みロックが割り当てられます。
読み込みロックも書き込みロックもかかっていない (つまり待機中のスレッドがない) 場合を除き、公平書き込みロック (再入不可能) を取得しようとするスレッドはブロックされます。(非ブロックの ReentrantReadWriteLock.ReadLock.tryLock()
メソッドと ReentrantReadWriteLock.WriteLock.tryLock()
メソッドはこの公平設定に従わず、待機中のスレッドには関係なく、可能であればロックを取得することに注意してください。)
このロックにより、リーダーとライターの両方が、ReentrantLock
のスタイルで読み取りまたは書き込みロックを再取得できるようになります。書き込むスレッドの保持する書き込みロックがすべて解放されるまで、再入不可能なリーダーは許可されません。
また、ライターは読み込みロックを取得できますが、リーダーが書き込みロックを取得することはできません。ほかのアプリケーションの間では、読み込みロック下で読み込みを実行するメソッドへの呼び出しまたはコールバック中に書き込みロックが保持される場合、再入可能性は有用です。リーダーが書き込みロックを取得しようとしても、成功しません。
再入可能性を利用すると、書き込みロックを取得してから読み込みロックを取得し、その後書き込みロックを解放するという方法で、書き込みロックから読み込みロックへの降格が可能になります。ただし、読み込みロックから書き込みロックへの昇格はできません。
読み込みロックと書き込みロックの両方が、ロック取得中の割り込みをサポートします。
Condition
のサポート
書き込みロックの提供する Condition
実装は、書き込みロックに関して、ReentrantLock.newCondition()
によって提供される Condition
実装が ReentrantLock
に対して実行するのと同じように動作します。この Condition
は当然、書き込みロックでのみ使用できます。
読み込みロックは Condition
をサポートしていないため、readLock().newCondition()
が UnsupportedOperationException
をスローします。
このクラスは、ロックが保持されるか競合するかを判別するメソッドをサポートします。これらのメソッドは、同期の制御用としてではなく、システム状態の監視用として設計されています。
このクラスの直列化は、組み込みロックと同様に動作します。直列化解除されたロックは、直列化時の状態にかかわらず、ロック解除状態になります。
使用例。次のコード例では、キャッシュを更新したあとにロックの降格を実行する方法を示します (入れ子を使用しない方法で複数のロックを処理する場合の例外処理は特に注意が必要)。
class CachedData {
Object data;
volatile boolean cacheValid;
final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
void processCachedData() {
rwl.readLock().lock();
if (!cacheValid) {
// Must release read lock before acquiring write lock
rwl.readLock().unlock();
rwl.writeLock().lock();
try {
// Recheck state because another thread might have
// acquired write lock and changed state before we did.
if (!cacheValid) {
data = ...
cacheValid = true;
}
// Downgrade by acquiring read lock before releasing write lock
rwl.readLock().lock();
} finally {
rwl.writeLock().unlock(); // Unlock write, still hold read
}
}
try {
use(data);
} finally {
rwl.readLock().unlock();
}
}
}
ReentrantReadWriteLocks を使用して、ある種の Collections の使用で並行性を改善できます。通常、これが価値があるのは、コレクションが大規模になることが予想され、ライタースレッドよりも多数のリーダースレッドによりアクセスされ、同期によるオーバーヘッドを上回るオーバーヘッドを持つ操作が含まれる場合です。例として、大規模で、並行アクセスが予想される TreeMap を使用するクラスを次に示します。
class RWDictionary {
private final Map<String, Data> m = new TreeMap<String, Data>();
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private final Lock r = rwl.readLock();
private final Lock w = rwl.writeLock();
public Data get(String key) {
r.lock();
try { return m.get(key); }
finally { r.unlock(); }
}
public String[] allKeys() {
r.lock();
try { return m.keySet().toArray(); }
finally { r.unlock(); }
}
public Data put(String key, Data value) {
w.lock();
try { return m.put(key, value); }
finally { w.unlock(); }
}
public void clear() {
w.lock();
try { m.clear(); }
finally { w.unlock(); }
}
}
このロックは、最大 65535 の再帰的書き込みロックおよび 65535 の読み込みロックをサポートします。これらの制限を超えようとすると、ロックしているメソッドから Error
がスローされます。
修飾子と型 | クラスと説明 |
---|---|
static class |
ReentrantReadWriteLock.ReadLock
readLock() メソッドによって返されたロックです。 |
static class |
ReentrantReadWriteLock.WriteLock
writeLock() メソッドによって返されたロックです。 |
コンストラクタと説明 |
---|
ReentrantReadWriteLock()
デフォルト (不公平) の順序プロパティーで、新規
ReentrantReadWriteLock を作成します。 |
ReentrantReadWriteLock(boolean fair)
指定された公平性ポリシーを使用して、新しい
ReentrantReadWriteLock を作成します。 |
修飾子と型 | メソッドと説明 |
---|---|
protected Thread |
getOwner()
現在書き込みロックを所有しているスレッドを返します。ロックが所有されていない場合は
null を返します。 |
protected Collection<Thread> |
getQueuedReaderThreads()
読み込みロックの取得を待機中のスレッドを含むコレクションを返します。
|
protected Collection<Thread> |
getQueuedThreads()
読み込みロックまたは書き込みロックのいずれかの取得を待機中のスレッドを含むコレクションを返します。
|
protected Collection<Thread> |
getQueuedWriterThreads()
書き込みロックの取得を待機中のスレッドを含むコレクションを返します。
|
int |
getQueueLength()
読み込みロックまたは書き込みロックの取得を待機中のスレッドの推定数を返します。
|
int |
getReadHoldCount()
現在のスレッドによる、このロック上の再入可能な読み込み保持数を照会します。
|
int |
getReadLockCount()
このロック用に保持されている読み込みロックの数を照会します。
|
protected Collection<Thread> |
getWaitingThreads(Condition condition)
書き込みロックに関連付けられた指定の状態を待機中のスレッドを含むコレクションを返します。
|
int |
getWaitQueueLength(Condition condition)
書き込みロックに関連付けられた指定の状態で待機中のスレッドの推定数を返します。
|
int |
getWriteHoldCount()
現在のスレッドによる、このロック上の再入可能な書き込み保持数を照会します。
|
boolean |
hasQueuedThread(Thread thread)
読み込みロックまたは書き込みロックの取得を待機中の指定のスレッドが存在するかどうかを照会します。
|
boolean |
hasQueuedThreads()
読み込みロックまたは書き込みロックの取得を待機中のスレッドが存在するかどうかを照会します。
|
boolean |
hasWaiters(Condition condition)
この書き込みロックに関連付けられた指定状態で待機しているスレッドが存在するかどうかを照会します。
|
boolean |
isFair()
このロックで公平性が true に設定されている場合は
true を返します。 |
boolean |
isWriteLocked()
書き込みロックがスレッドに保持されているかどうかを照会します。
|
boolean |
isWriteLockedByCurrentThread()
現在のスレッドがこの書き込みロックを保持しているどうかを照会します。
|
ReentrantReadWriteLock.ReadLock |
readLock()
読み込みに使用するロックを返します。
|
String |
toString()
このロックおよびその状態を識別する文字列を返します。
|
ReentrantReadWriteLock.WriteLock |
writeLock()
書き込みに使用するロックを返します。
|
public ReentrantReadWriteLock()
ReentrantReadWriteLock
を作成します。public ReentrantReadWriteLock(boolean fair)
ReentrantReadWriteLock
を作成します。fair
- このロックが公平順序付けポリシーを使用する場合は true
public ReentrantReadWriteLock.WriteLock writeLock()
ReadWriteLock
writeLock
、インタフェース: ReadWriteLock
public ReentrantReadWriteLock.ReadLock readLock()
ReadWriteLock
readLock
、インタフェース: ReadWriteLock
public final boolean isFair()
true
を返します。true
protected Thread getOwner()
null
を返します。このメソッドが所有者ではないスレッドによって呼び出される場合、戻り値には現在のロック状態の最大限の近似値が反映されます。たとえば、ロックの取得を試みていてまだ取得していないスレッドが存在する場合も、所有者は一時的に null
になる場合があります。このメソッドは、より包括的なロック監視機能を提供するサブクラスの構築を容易にする目的で設計されています。null
public int getReadLockCount()
public boolean isWriteLocked()
true
。それ以外の場合は false
public boolean isWriteLockedByCurrentThread()
true
。それ以外の場合は false
public int getWriteHoldCount()
public int getReadHoldCount()
protected Collection<Thread> getQueuedWriterThreads()
protected Collection<Thread> getQueuedReaderThreads()
public final boolean hasQueuedThreads()
true
が返されても、ほかのいずれかのスレッドがロックを取得することは保証されていません。このメソッドは、主にシステム状態の監視に使用する目的で設計されています。true
public final boolean hasQueuedThread(Thread thread)
true
が返されても、このスレッドがロックを取得することは保証されていません。このメソッドは、主にシステム状態の監視に使用する目的で設計されています。thread
- スレッドtrue
NullPointerException
- スレッドが null の場合public final int getQueueLength()
protected Collection<Thread> getQueuedThreads()
public boolean hasWaiters(Condition condition)
true
が返されても、将来 signal
がスレッドを起動させることは保証されていません。このメソッドは、主にシステム状態の監視に使用する目的で設計されています。condition
- 状態true
IllegalMonitorStateException
- このロックを保持していない場合IllegalArgumentException
- 指定された状態がこのロックと関連付けられていない場合NullPointerException
- 状態が null の場合public int getWaitQueueLength(Condition condition)
condition
- 状態IllegalMonitorStateException
- このロックを保持していない場合IllegalArgumentException
- 指定された状態がこのロックと関連付けられていない場合NullPointerException
- 状態が null の場合protected Collection<Thread> getWaitingThreads(Condition condition)
condition
- 状態IllegalMonitorStateException
- このロックを保持していない場合IllegalArgumentException
- 指定された状態がこのロックと関連付けられていない場合NullPointerException
- 状態が null の場合 バグまたは機能を送信
詳細な API リファレンスおよび開発者ドキュメントについては、Java SE のドキュメントを参照してください。そのドキュメントには、概念的な概要、用語の定義、回避方法、有効なコード例などの、開発者を対象にしたより詳細な説明が含まれています。
Copyright © 1993, 2013, Oracle and/or its affiliates. All rights reserved.