title: Wait for a lock to unlock, without locking it after the unlock
body: <p>Sorry if the title is a tongue twister but I couldn't phrase it better since that's exactly what I want to do.</p>
  
  <p>I have this method/code:</p>
  
  <pre><code>// No need fairness (false) the first to get it is good to go
  private final Lock TEST = new ReentrantLock(false)
  
  public methodCalledByMultipleThreads() {
  
      // 1st code section - no concurrency problems
      // regardless of what happen in section 2 a thread that just called
      // this function should always be able to run section 1
  
      // 2nd code section begin
  
      if (rare_condition &amp;&amp; TEST.tryLocking()) {
          // check again to avoid limit cases where "rare_condition" value
          // is invalidated by another thread (who ran "important stuffs")
          // and just released/unlock TEST with "TEST.unlock();"
          if (check_rare_condition_again) {
              // ##### do "important stuffs" ##### 
              // release lock
              TEST.unlock();
          }
      }
  
      TEST.waitUntilUnlocked(); // this is what I actually would like to do
      // ##### do other stuffs ##### 
  
  }
  </code></pre>
  
  <p>Of course "waitUntilUnlocked" should not lock "TEST" when the wait is ended. I've tried to get the wanted behavior with an hacky usage of Semaphore... which is really bad, semaphores are not made for that and also cause overhead in this case (internal permits count isn't counting anything... is just a fancy lock):</p>
  
  <pre><code>private final Lock TEST = new ReentrantLock(false)
  
  // absurd high value (Integer.MAX_VALUE) for permits, to allow "virtually"
  // infinite threads to works with this code
  private final Semaphore SEM = new Semaphore(Integer.MAX_VALUE, true);
  
  public methodCalledByMultipleThreads() {
  
      // 1st code section
  
      // 2nd code section begin
  
      if (rare_condition &amp;&amp; TEST.tryLocking()) {
          if (check_rare_condition_again) {
  
              // waits to gets all permits
              SEM.acquireUninterruptibly(Integer.MAX_VALUE);
  
              // ##### do important stuffs ##### 
  
              // release all permits
              SEM.release(Integer.MAX_VALUE);
              // release lock
              TEST.unlock();
          }
      }
      // ask one permit
      SEM.acquireUninterruptibly();
      //  ##### do other stuffs ##### 
      // release one permit
      SEM.release();
  
  }
  </code></pre>
  
  <p>The above solution is "works" (by luck on the actual implementation the code is enough slow to not cause any edge cases... for now) but is theoretically wrong since "SEM.release(Integer.MAX_VALUE);" and "TEST.unlock();" should be one thing.</p>
  
  <p>How can I get this behavior without this ugly hack?</p>