モジュール java.base

クラスReentrantReadWriteLock

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


    public class ReentrantReadWriteLock
    extends Object
    implements ReadWriteLock, Serializable
    ReentrantLockと同様のセマンティックスをサポートするReadWriteLockの実装です。

    このクラスには次の特性があります。

    • 取得順序

      このクラスは、ロック・アクセスに対するリーダーまたはライターの優先順序を規定しません。 ただし、オプションの公平性ポリシーをサポートします。

      不公平モード(デフォルト)
      不公平として構築された場合は(デフォルト)、読み込みおよび書込みロックに入る順序は指定されず、再入可能性制約に従います。 継続的に競合していた不公平ロックでは、1つ以上のリーダーまたはライター・スレッドを無期限に延期することがありますが、通常は公平ロックよりスループットが高くなります。
      公平モード
      公平として構築された場合、スレッドは近似の到着順ポリシーを使用してエントリで競合します。 現在保持されているロックが解放されると、待機時間のもっとも長い単一のライター・スレッドに書込みロックが割り当てられるか、待機中のどのライター・スレッドよりも長く待機しているリーダー・スレッドのグループが存在する場合は、そのグループに読込みロックが割り当てられます。

      書込みロックが保持されている場合や待機中のライター・スレッドが存在する場合、公平読込みロック(再入不可能)を取得しようとするスレッドはブロックされます。 そのようなスレッドは、現在待機中のライター・スレッドのうちもっとも古いスレッドが書込みロックを取得して解放するまで、読込みロックを取得しません。 もちろん、待機中のライターが待機を中止し、キュー内でもっとも長く待機している1つ以上のリーダー・スレッドに書込みロックがかかっていない場合は、それらのリーダーに読込みロックが割り当てられます。

      読込みロックも書込みロックもかかっていない(つまり待機中のスレッドがない)場合を除き、公平書込みロック(再入不可能)を取得しようとするスレッドはブロックされます。 (非ブロックのReentrantReadWriteLock.ReadLock.tryLock()メソッドとReentrantReadWriteLock.WriteLock.tryLock()メソッドはこの公平設定に従わず、待機中のスレッドには関係なく、可能であればロックをただちに取得することに注意してください。)

    • 再入可能性

      このロックにより、リーダーとライターの両方が、ReentrantLockのスタイルで読み取りまたは書込みロックを再取得できるようになります。 書き込むスレッドの保持する書込みロックがすべて解放されるまで、再入不可能なリーダーは許可されません。

      また、ライターは読込みロックを取得できますが、リーダーが書込みロックを取得することはできません。 ほかのアプリケーションの間では、読込みロック下で読込みを実行するメソッドへの呼び出しまたはコールバック中に書込みロックが保持される場合、再入可能性は有用です。 リーダーが書込みロックを取得しようとしても、成功しません。

    • ロックの降格

      再入可能性を利用すると、書込みロックを取得してから読込みロックを取得し、その後書込みロックを解放するという方法で、書込みロックから読込みロックへの降格が可能になります。 ただし、読込みロックから書込みロックへの昇格はできません

    • ロック取得の割り込み

      読込みロックと書込みロックの両方が、ロック取得中の割込みをサポートします。

    • Conditionのサポート

      書込みロックの提供するCondition実装は、書込みロックに関して、ReentrantLock.newCondition()によって提供されるCondition実装がReentrantLockに対して実行するのと同じように動作します。 このConditionは当然、書込みロックでのみ使用できます。

      読込みロックはConditionをサポートしていないため、readLock().newCondition()UnsupportedOperationExceptionをスローします。

    • インストゥルメンテーション

      このクラスは、ロックが保持されるか競合するかを判別するメソッドをサポートします。 これらのメソッドは、同期の制御用としてではなく、システム状態の監視用として設計されています。

    このクラスの直列化は、組込みロックと同様に動作します。直列化解除されたロックは、直列化時の状態にかかわらず、ロック解除状態になります。

    使用例 次のコード例では、キャッシュを更新したあとにロックの降格を実行する方法を示します(入れ子を使用しない方法で複数のロックを処理する場合の例外処理は特に注意が必要)。

     
     class CachedData {
       Object data;
       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<>();
       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 List<String> allKeys() {
         r.lock();
         try { return new ArrayList<>(m.keySet()); }
         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がスローされます。

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

      コンストラクタ 
      コンストラクタ 説明
      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​()
      書込みに使用するロックを返します。
    • コンストラクタの詳細

      • ReentrantReadWriteLock

        public ReentrantReadWriteLock​()
        デフォルト(不公平)の順序プロパティで、新規ReentrantReadWriteLockを作成します。
      • ReentrantReadWriteLock

        public ReentrantReadWriteLock​(boolean fair)
        指定された公平性ポリシーを使用して、新しいReentrantReadWriteLockを作成します。
        パラメータ:
        fair - このロックが公平順序付けポリシーを使用する場合はtrue
    • メソッドの詳細

      • isFair

        public final boolean isFair​()
        このロックで公平性がtrueに設定されている場合はtrueを返します。
        戻り値:
        このロックで公平性がtrueに設定されている場合はtrue
      • getOwner

        protected Thread getOwner​()
        現在書込みロックを所有しているスレッドを返します。ロックが所有されていない場合はnullを返します。 このメソッドが所有者ではないスレッドによって呼び出される場合、戻り値には現在のロック状態の最大限の近似値が反映されます。 たとえば、ロックの取得を試みていてまだ取得していないスレッドが存在する場合も、所有者は一時的にnullになる場合があります。 このメソッドは、より包括的なロック監視機能を提供するサブクラスの構築を容易にする目的で設計されています。
        戻り値:
        所有者。所有されていない場合はnull
      • getReadLockCount

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

        public boolean isWriteLocked​()
        書込みロックがスレッドに保持されているかどうかを照会します。 このメソッドは、同期の制御用としてではなく、システム状態の監視用として設計されています。
        戻り値:
        いずれかのスレッドが書込みロックを保持している場合はtrue。それ以外の場合はfalse
      • isWriteLockedByCurrentThread

        public boolean isWriteLockedByCurrentThread​()
        現在のスレッドがこの書込みロックを保持しているどうかを照会します。
        戻り値:
        現在のスレッドが書込みロックを保持している場合はtrue。それ以外の場合はfalse
      • getWriteHoldCount

        public int getWriteHoldCount​()
        現在のスレッドによる、このロック上の再入可能な書込み保持数を照会します。 ライター・スレッドは、ロック解除アクションと一致しない各ロック・アクション用のロックを保持します。
        戻り値:
        現在のスレッドの、書込みロックに対する保持数。現在のスレッドがこのロックを保持していない場合はゼロ
      • getReadHoldCount

        public int getReadHoldCount​()
        現在のスレッドによる、このロック上の再入可能な読込み保持数を照会します。 読込みスレッドには、ロック解除アクションと一致しないロック・アクションごとに、ロック保持が存在します。
        戻り値:
        現在のスレッドの、読込みロックに対する保持数。現在のスレッドがこのロックを保持していない場合はゼロ
        導入されたバージョン:
        1.6
      • getQueuedWriterThreads

        protected Collection<Thread> getQueuedWriterThreads​()
        書込みロックの取得を待機中のスレッドを含むコレクションを返します。 実際のスレッド・セットは、結果の構築中にも動的に変化する可能性があるため、返されるコレクションは最善の努力を払った上での推定に過ぎません。 返されるコレクションの要素には、特定の順序は存在しません。 このメソッドは、より包括的なロック監視機能を提供するサブクラスの構築を容易にする目的で設計されています。
        戻り値:
        スレッドのコレクション
      • getQueuedReaderThreads

        protected Collection<Thread> getQueuedReaderThreads​()
        読込みロックの取得を待機中のスレッドを含むコレクションを返します。 実際のスレッド・セットは、結果の構築中にも動的に変化する可能性があるため、返されるコレクションは最善の努力を払った上での推定に過ぎません。 返されるコレクションの要素には、特定の順序は存在しません。 このメソッドは、より包括的なロック監視機能を提供するサブクラスの構築を容易にする目的で設計されています。
        戻り値:
        スレッドのコレクション
      • hasQueuedThreads

        public final boolean hasQueuedThreads​()
        読込みロックまたは書込みロックの取得を待機中のスレッドが存在するかどうかを照会します。 取消しはいつでも発生する可能性があるため、trueが返されても、ほかのいずれかのスレッドがロックを取得することは保証されていません。 このメソッドは、主にシステム状態の監視に使用する目的で設計されています。
        戻り値:
        ロックの取得を待機中のほかのスレッドが存在する可能性がある場合はtrue
      • hasQueuedThread

        public final boolean hasQueuedThread​(Thread thread)
        読込みロックまたは書込みロックの取得を待機中の指定のスレッドが存在するかどうかを照会します。 取消しはいつでも発生する可能性があるため、trueが返されても、このスレッドがロックを取得することは保証されていません。 このメソッドは、主にシステム状態の監視に使用する目的で設計されています。
        パラメータ:
        thread - スレッド
        戻り値:
        指定されたスレッドがキューに入れられており、このロックを待機中である場合はtrue
        例外:
        NullPointerException - スレッドがnullの場合
      • getQueueLength

        public final int getQueueLength​()
        読込みロックまたは書込みロックの取得を待機中のスレッドの推定数を返します。 このメソッドが内部のデータ構造をトラバースしている間にも、スレッド数が動的に変化する場合があるため、この値は推定に過ぎません。 このメソッドは、同期の制御用としてではなく、システム状態の監視用として設計されています。
        戻り値:
        このロックを待機しているスレッドの推定数
      • getQueuedThreads

        protected Collection<Thread> getQueuedThreads​()
        読込みロックまたは書込みロックのいずれかの取得を待機中のスレッドを含むコレクションを返します。 実際のスレッド・セットは、結果の構築中にも動的に変化する可能性があるため、返されるコレクションは最善の努力を払った上での推定に過ぎません。 返されるコレクションの要素には、特定の順序は存在しません。 このメソッドは、より包括的な監視機能を提供するサブクラスの構築を容易にする目的で設計されています。
        戻り値:
        スレッドのコレクション
      • hasWaiters

        public boolean hasWaiters​(Condition condition)
        この書込みロックに関連付けられた指定状態で待機しているスレッドが存在するかどうかを照会します。 タイム・アウトおよび割込みはいつでも発生する可能性があるため、trueが返されても、将来signalがスレッドを起動させることは保証されていません。 このメソッドは、主にシステム状態の監視に使用する目的で設計されています。
        パラメータ:
        condition - 状態
        戻り値:
        待機中のスレッドが存在する場合はtrue
        例外:
        IllegalMonitorStateException - このロックを保持していない場合
        IllegalArgumentException - 指定された状態がこのロックと関連付けられていない場合
        NullPointerException - 状態がnullの場合
      • getWaitQueueLength

        public int getWaitQueueLength​(Condition condition)
        書込みロックに関連付けられた指定の状態で待機中のスレッドの推定数を返します。 タイム・アウトおよび割り込みの発生する可能性はいつでも存在するため、推定数は、実際の待機者数に関する上限を示すに過ぎません。 このメソッドは、同期の制御用としてではなく、システム状態の監視用として設計されています。
        パラメータ:
        condition - 状態
        戻り値:
        待機中のスレッドの推定数
        例外:
        IllegalMonitorStateException - このロックを保持していない場合
        IllegalArgumentException - 指定された状態がこのロックと関連付けられていない場合
        NullPointerException - 状態がnullの場合
      • getWaitingThreads

        protected Collection<Thread> getWaitingThreads​(Condition condition)
        書込みロックに関連付けられた指定の状態を待機中のスレッドを含むコレクションを返します。 実際のスレッド・セットは、結果の構築中にも動的に変化する可能性があるため、返されるコレクションは最善の努力を払った上での推定に過ぎません。 返されるコレクションの要素には、特定の順序は存在しません。 このメソッドは、より包括的な状態監視機能を提供するサブクラスの構築を容易にする目的で設計されています。
        パラメータ:
        condition - 状態
        戻り値:
        スレッドのコレクション
        例外:
        IllegalMonitorStateException - このロックを保持していない場合
        IllegalArgumentException - 指定された状態がこのロックと関連付けられていない場合
        NullPointerException - 状態がnullの場合
      • toString

        public String toString​()
        このロックおよびその状態を識別する文字列を返します。 状態は括弧で囲まれ、文字列"Write locks ="に続いて再入可能として保持されている書込みロックの数、および文字列"Read locks ="に続いて保持されている読込みロックの数が含まれます。
        オーバーライド:
        toString、クラス: Object
        戻り値:
        このロックおよびその状態を識別する文字列