0

多くのチュートリアルで、ReadWriteLock の再入不可の実装の下に出くわしました。

public class ReadWriteLock{

    private int readers       = 0;
    private int writers       = 0;
    private int writeRequests = 0;

    public synchronized void lockRead() throws InterruptedException{
      while(writers > 0 || writeRequests > 0){
        wait();
      }
    readers++;
    }

    public synchronized void unlockRead(){
      readers--;
      notifyAll();
    }

    public synchronized void lockWrite() throws InterruptedException{
      writeRequests++;

      while(readers > 0 || writers > 0){
        wait();
      }
      writeRequests--;
      writers++;
    }

    public synchronized void unlockWrite() throws InterruptedException{
      writers--;
      notifyAll();
    }
}

質問:

このクラスのオブジェクト (たとえばlock) は、同期のためにすべてのリーダー スレッドとライター スレッドで共有されます。

リーダー T1 が を呼び出しlock.lockRead()、これがロック オブジェクトのロックを取得し、同時にリーダー T2lockRead()が同じオブジェクトを呼び出すとします。ただし、T1 は既にオブジェクトをロックしているため、T2 はブロックされ、Queue で待機する必要があります。

では、このコードでは、複数のリーダーが同時に readLock を設定できるようにするにはどうすればよいでしょうか?

私がいつこれを間違えたのか教えてください。

4

1 に答える 1

2

2 つのスレッドがメソッドの本体を同時に実行できないことは事実です。lockRead()ただし、リーダー/ライター パターンが正しく動作し、期待されるパフォーマンスを発揮するためには、これは必要ありません。

重要なのは、アクティブなライターがいない (呼び出されていない)lockRead()場合、メソッドがすぐに戻ることです。waitメソッドが終了するとロックが解放されるため、別のスレッドも読み取りロックを取得できます。

したがって、はい、読み取りロックを取得する (インクリメントするreaders) 行為はシリアル化されます。しかし、それは非常に迅速に行われるため、問題なく機能します。

説明する:

private ReadWriteLock lock = new ReadWriteLock(); // this instance is shared by all threads

public void ReadSomething() {
    try {
        lock.lockRead(); // serialized, but very quick

        PerformWork(); // potentially slower, but is concurrent
    } finally {
        lock.unlockRead(); // serialized, but very quick
    }
}

2 つのスレッドが上記のReadSomething()メソッドをまったく同時に実行しようとした場合lock.lockRead()、一度に実行できるスレッドは 1 つだけです。ただし、そのメソッドがスレッドの 1 つに戻るとすぐに、2 番目のスレッドもそれを実行できるようになります。への呼び出しlock.lockRead()は非常に迅速に行われるため、一方のスレッドが他方のスレッドを待機していたことに気付くことさえできません。

重要なのは、両方のスレッドが同時により多くの時間を消費PerformWork()して実行できることです。

于 2016-07-27T19:49:15.760 に答える