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此类的一个对象(例如)在所有读取器和写入器线程之间共享以进行同步。

让我们假设 Reader T1 调用lock.lockRead(),这获得了锁对象上的锁,而 Reader T2 同时调用lockRead()了同一个对象。但是 T1 已经锁定了对象,所以 T2 应该被阻塞并在队列中等待。

那么,代码是如何让多个阅读器同时设置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()。但是一旦该方法为其中一个线程返回,第二个线程也将能够执行它。并且调用lock.lockRead()发生得如此之快,以至于您甚至无法注意到一个线程正在等待另一个线程。

重要的是两个线程能够同时执行更耗时PerformWork()的任务。

于 2016-07-27T19:49:15.760 回答