ReadWriteLocks-(非重入)它如何支持多个读取器获取读锁

时间:2016-07-27 19:33:40

标签: java multithreading readwritelock

我在许多教程中遇到过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?

当我弄错了时,请纠正我。

1 个答案:

答案 0 :(得分:2)

确实没有2个线程可以同时执行lockRead()方法的 body 。但是,读取器/写入器模式无需正常工作并具有预期的性能。

重要的是,如果没有活动的作者(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()