title: Why in ReentrantReadWriteLock, should the readLock() be unlocked before writeLock().lock()?
body: <p>From the <a href="https://docs.oracle.com/javase/6/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html" rel="nofollow noreferrer">ReentrantReadWriteLock class javadoc</a>:</p>
  
  <pre><code>void processCachedData() {
    rwl.readLock().lock();
    if (!cacheValid) {
       // Must release read lock before acquiring write lock
  5:   rwl.readLock().unlock();
  6:   rwl.writeLock().lock();
       // Recheck state because another thread might have acquired
       //   write lock and changed state before we did.
       if (!cacheValid) {
         data = ...
         cacheValid = true;
       }
       // Downgrade by acquiring read lock before releasing write lock
  14:  rwl.readLock().lock();
  15:  rwl.writeLock().unlock(); // Unlock write, still hold read
    }
  
    use(data);
    rwl.readLock().unlock();
  }
  </code></pre>
  
  <p>Why must we release the read lock before acquiring the write lock as written in the comment? If the current thread holds the read lock, then it should be allowed to acquire the write lock when other threads are not reading anymore, regardless of whether the current thread also holds the read lock. This is the behavior I would expect.</p>
  
  <p>I would expect the lock upgrade at lines 5 and 6 and the lock downgrade at lines 14 and 15 to be done internally in the ReentrantReadWriteLock class. Why is that not possible?</p>
  
  <p>In other words, I would expect the code to work fine like this:</p>
  
  <pre><code>void processCachedData() {
    rwl.readLock().lock();
    if (!cacheValid) {
       // The readlock is upgraded to writeLock when other threads 
       // release their readlocks.
       rwl.writeLock().lock();
       // no need to recheck: other threads can't have acquired  
       // the write lock since this thread still holds also the readLock!!!
       if (!cacheValid) {  
         data = ...
         cacheValid = true;
       }
       // Downgrade by acquiring read lock before releasing write lock
       rwl.writeLock().unlock(); // Unlock write, still hold read
    }
  
    use(data);
    rwl.readLock().unlock();
  }
  </code></pre>
  
  <p>This looks like a much better and safer way to handle locking, doesn't it?</p>
  
  <p>Can somebody explain the reason for this weird implementation? Thanks.</p>