在许多教程中,我遇到了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)在所有读取器和写入器线程之间共享以进行同步。

假设Reader T1调用lock.lockRead(),这将获取锁定对象上的锁,而Reader T2同时在同一对象上调用lockRead()。但是T1已经锁定了对象,因此T2应该被阻塞并在队列中等待。

那么,代码如何允许多个读取器同时设置readLock?

请纠正我,知道我什么时候错了。

最佳答案

的确,没有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()。但是,只要该方法为其中一个线程返回,第二个线程也将能够执行该方法。而且对lock.lockRead()的调用是如此之快,以至于您甚至无法注意到一个线程正在等待另一个线程。

重要的是两个线程都能够同时执行更多耗时的PerformWork()

07-25 22:13