简体   繁体   中英

Confused with custom read write lock implementation

I have seen some posts about the custom read-write lock implementation in java using wait/notify . It looks like:

 public class ReadWriteLock{

  private int readers;
  private int writers;
  private int writeRequests;

  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();
  }
}

I cannot comprehend how it could correctly work, unless I have not understood correctly how wait/notify really works. Assuming the read requests and consequently Threads are more, my questions are:

  • If read Threads acquire repeatedly the lock on the instance, how could a write Thread increase the variable writeRequests , since it can be increased only within a synchronized method. Hence a Thread should acquire first the lock to do it (if I am not mistaken). As long as a read Thread calls wait only if writeRequests or writers are greater than 0 , how can a write Thread have the chance to acquire the lock?

  • Based on the above presumptions and statements, how could more than one read Threads access a method at the same time, since they should first call lockRead() which is synchronized as well?

Edit : After seeing you edit to the question, you're asking what happens when multiple threads call wait() inside the same synchronized blocks - see this for a detailed explanation on what is called 'releasing the monitor' - http://www.artima.com/insidejvm/ed2/threadsynchP.html

To simplify things:

  • Synchronized methods are like synchronized(this) blocks.
  • calling wait() inside synchronized blocks release the lock and switches the thread to WAITING state. in this scenario other threads can acquire the lock on the same object and possibly notify the other waiting threads on state change (your unlock methods demonstrate that) by using the same object waited on ( this in our case, because you're using synchronized methods)
  • If you map the possible scenarios for calling each method according to that priniciple you can see that methods are either non-waiting ( unlockRead() / unlockWrite() ) - meaning they can block on mutual exclusion upon entry, but don't run any blocking code(and end swiftly). Or, they are waiting but non-blocking ( lockRead() / lockWrite() ) - Just like the unlock methods with the addition their execution could potentially be stalled, however they don't block, but rather wait in such scenarios.
  • So in any case you can consider your code as non-blocking and therefor it doesn't pose any real issue ( at least none that I can see ).
  • That said, you should protect against unlocking non-existent locks, causes that'll cause an undesired behavior where counters would go below 0 ( which would in turn affect the lock methods)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM