インタビュアー: ReadWriteLock は読み取りと書き込みの間で相互に排他的ですか?

 
  
 
  
您好,我是路人,更多优质文章见个人博客:http://itsoku.com


開発中に同時実行の問題が発生した場合、一般的にロックが使用されますが、同期には読み取りと読み取りの間の相互排他という明らかなパフォーマンスの問題があります。

ReadWriteLock は、JDK5 で提供される読み書き分離ロックです。読み取り/書き込み分離ロックは、ロックの競合を減らし、システムのパフォーマンスを向上させるのに効果的に役立ちます。

ReadWriteLock は一連のロックを管理します。1 つは読み取り専用ロック、もう 1 つは書き込みロックです。

Java 同時実行ライブラリの ReetrantReadWriteLock は ReadWriteLock インターフェイスを実装し、リエントラント機能を追加します。

読み取り-書き込みロック ReentrantReadWriteLock: 読み取り-読み取り共有、読み取り-書き込み相互排他、書き込み-書き込み相互排他。読み取り-書き込みロックは、読み取りロックと書き込みロックを分離することで、読み取りロック、書き込みロックのペアのロックを維持します。 、同時実行性が比較的高くなるように、一般的な排他ロックが大幅に改善されました。読み取りが多く書き込みが少ない場合、読み取り/書き込みロックは排他的ロックよりも優れた同時実行性とスループットを提供できます。

04fcd9d2fc6a514d21fb7b913d638705.png

ソース コードから、読み取り/書き込みロックは同期機能を実現するためにキュー シンクロナイザー Sync (AQS) にも依存しており、読み取り/書き込みステータスはそのシンクロナイザーの同期ステータスであることがわかります。推奨: Java の高度なビデオ リソース

以下は、読み取り-読み取り共有、読み取り-書き込み相互排他、および書き込み-書き込み相互排他を説明する例です。

コードは以下のように表示されます:

public class ReentrantWriteReadLockTest {
    ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    ReadLock readLock = lock.readLock();
    WriteLock writeLock = lock.writeLock();
    
    public void read(){
        try {
            readLock.lock();
            System.out.println("线程"+Thread.currentThread().getName()+"进入。。。");
            Thread.sleep(3000);
            System.out.println("线程"+Thread.currentThread().getName()+"退出。。。");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            readLock.unlock();
        }
    }
    
    public void write(){
        try {
            writeLock.lock();
            System.out.println("线程"+Thread.currentThread().getName()+"进入。。。");
            Thread.sleep(3000);
            System.out.println("线程"+Thread.currentThread().getName()+"退出。。。");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            writeLock.unlock();
        }
    }
    
 
    public static void main(String[] args) {
        final ReentrantWriteReadLockTest wr = new ReentrantWriteReadLockTest();
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                wr.read();
            }
        }, "t1");
        Thread t2 = new Thread(new Runnable() {
            public void run() {
                wr.read();
            }
        }, "t2");
        Thread t3 = new Thread(new Runnable() {
            public void run() {
                wr.write();
            }
        }, "t3");
        Thread t4 = new Thread(new Runnable() {
            public void run() {
                wr.write();
            }
        }, "t4");
        
        t1.start();
        t2.start();
        //t3.start();
        //t4.start();
    }
}

スレッド t1 と t2 を開始すると、結果は次のようになります。

f123d24c6644c316e65db378ceb73422.png

スレッド t1 と t2 は同時に入ることができます。これが説明されています读读共享

スレッド t2 と t3 を開始すると、結果は次のようになります。

6b7a750d08cf866696a51d8aa01c0c4f.png

スレッドは、別のスレッドが終了するまで待機してから開始する必要があります。これが説明されています读写互斥

スレッド t3 と t4 を開始すると、結果は次のようになります。

6d9951e64aee36269dae65c8d3cf7ea2.png

スレッドは、別のスレッドが終了するまで待機してから開始する必要があります。これが説明されています写写互斥

もっと良い記事を

  1. Java 高同時実行性シリーズ (全 34 記事)

  2. MySqlマスターシリーズ(全27記事)

  3. Maven マスター シリーズ (全 10 件)

  4. Mybatisシリーズ(全12記事)

  5. データベースとキャッシュの整合性の一般的な実装について話す

  6. インターフェイスの冪等性は非常に重要ですが、それは何ですか? それを達成するにはどうすればよいでしょうか?

  7. ジェネリックは少し難しく、多くの人を混乱させるでしょう。それはあなたがこの記事を読んでいないからです。

↓↓↓ 点击阅读原文,直达个人博客
你在看吗

おすすめ

転載: blog.csdn.net/likun557/article/details/131971322