ベスト(20)面接官:読み書きロックについて--ReadWriteLock

2949 ワード

今日はJavaの読み書きロック-ReadWriteLock、ReadWriteLockはインタフェースで、実装クラスはReentrantReadWriteLockで、名前の翻訳を見ていると読み書きロックに再アクセスできます.
なぜJavaはそんなに多くの種類のロックをしたのか、異なるシーンは異なる適切な組み合わせをして性能と使用の最適化を達成する必要があるため、読み書きロックの使用シーンは読み書きが少ないことです.
読み書きロックは何ですか?
読み書きロックとは、複数のスレッドが共有変数を同時に読み取ることができるが、1つのスレッドが共有変数を書くことしか許されず、共有変数を書くときも読み方の操作をブロックする読み書きロックの2つのケースに分けられる.これにより、読むときに反発することなく、読む効率が向上します.
再ロックは何ですか?
再入可能ロックとは、同じスレッド内で外層関数がロックされている場合、内層関数もロックを取得することができます.つまり、1つのスレッドを介して同期コードブロックに再びアクセスすると、再入不可ではなく、自分が取得したロックを取得することができます.簡単な例を見てみましょう
    public void doSth(){   //    
        lock.lock();
        do();  //    
        lock.unlock();
    }
    public void do(){
        lock.lock();
        //do something
        lock.unlock();
     }


再入可能ロックこのように上記のコードを使用するのは問題ありません.再入不可ロックのような呼び出しは許可されません.
JavadocのReentrantReadWriteLockの例を見てみましょう.主にキャッシュデータを取得する例を処理します.
 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();
     }
   }
 }



使用は簡単なのか、ReentrantLockに比べて複数のロールがあり、1つはリードロックであり、1つはライトロックであることがわかります.
読み書きロックの昇降段
上のコードに言及されています
Must release read lock before acquiring write lock(書き込みロックを取得する前に読み取りロックを解放する必要があります)
つまり、読み書きロックはロックのアップグレードを許可せず、直接読み書きロックから書き込みロックにアップグレードすることはできません.リードロックがまだ解放されていない場合、ライトロックが取得されると、ライトロックが永久に待機し、最終的には関連スレッドがブロックされ、GGになります.このように使ってはいけないことを忘れないでください.
しかしロックのダウングレードは許可されています
Downgrade by acquiring read lock before releasing write lock
つまり、書き込みロックを解除する前に、読み込みロックを取得してロックのダウングレードを達成することができます!
リード・ライト・ロックには、ライト・ロックが条件変数をサポートするnewConditionであり、リード・ロックが条件変数をサポートしない場合、リード・ロック呼び出しnewConditionUnsupportedOperationExceptionを投げます.
読み書きロックはjava.util.concurrent.locks.Lockインタフェースを実現しているので、tryLock()、lockInterruptibly()などの方法はすべてサポートされており、公平ロックと非公平ロックのモードもサポートされており、下層もAbstractQueuedSynchronizerに基づいて実現されているので、公平と非公平ロックの実現については面接官:Javaの信号量を話してください.Semaphore私のこの文章