docs: synchronized int release(Locker locker) {
  
          //-----------------------------------------------------------------
          // A transaction can be both a holder and a waiter if
          // it is attempting to convert a shared lock to an exclusive one.
          //-----------------------------------------------------------------
  
          if (holders.remove(locker) != null) {
              numUsers--;
          }
  
          Waiter waiter = (Waiter) waiters.remove(locker);
          if (waiter != null) {
              numUsers--;
              synchronized (waiter) {
                  waitQ.removeElement(waiter);
                  waiter.released = true;
                  lockMgr.unwaitEvent(waiter);
                  waiter.notify();
              }
          }
  
          //----------------------------------------------------------------
          // Q: Do we care about attempts to release locks for given locker
          //    that are not held by that locker? If so fail here if locker
          //    was neither holder nor waiter.
          //----------------------------------------------------------------
  
          //----------------------------------------------------------
          // If there are no more holders then wake up all compatible
          // waiters from the head of the wait queue. This imposes a
          // strict FIFO scheduling.
          //----------------------------------------------------------
  
          if (holders.size() == 0) {
  
              //-------------------------------------------------
              // Grant first waiter the lock and then see if the
              // remaining waiters are compatible.
              //-------------------------------------------------
  
              if (waiters.size() > 0) {
                  Waiter newHolder = (Waiter) waitQ.firstElement();
                  synchronized (newHolder) {
                      waiters.remove(newHolder.locker);
                      waitQ.removeElementAt(0);
                      holders.put(newHolder.locker, newHolder.locker);
                      this.mode = newHolder.mode;
                      lockMgr.unwaitEvent(newHolder);
                      newHolder.notify();
                  }
              }
  
              //--------------------------------------------------
              // If lock now held in exclusive mode we are done,
              // else grant lock to all waiters at head of queue
              // that are requesting the lock in the SHARED mode.
              //--------------------------------------------------
  
              if (mode == LockManager.EXCLUSIVE) {
                  return numUsers;
              }
  
              while (waiters.size() > 0) {
                  Waiter newHolder = (Waiter) waitQ.firstElement();
                  if (newHolder.mode == LockManager.EXCLUSIVE) {
                      return numUsers;
                  }
  
                  synchronized (newHolder) {
                      waiters.remove(newHolder.locker);
                      waitQ.removeElementAt(0);
                      holders.put(newHolder.locker, newHolder.locker);
                      lockMgr.unwaitEvent(newHolder);
                      newHolder.notify();
                  }
              }
          }
          return numUsers;
  
      }