/**
   * Perform one release of the mutex if the calling thread is the same thread that acquired it. If
   * the thread had made multiple calls to acquire, the mutex will still be held when this method
   * returns.
   *
   * @throws Exception ZK errors, interruptions, current thread does not own the lock
   */
  @Override
  public void release() throws Exception {
    /*
       Note on concurrency: a given lockData instance
       can be only acted on by a single thread so locking isn't necessary
    */

    Thread currentThread = Thread.currentThread();
    LockData lockData = threadData.get(currentThread);
    if (lockData == null) {
      throw new IllegalMonitorStateException("You do not own the lock: " + basePath);
    }

    int newLockCount = lockData.lockCount.decrementAndGet();
    if (newLockCount > 0) {
      return;
    }
    if (newLockCount < 0) {
      throw new IllegalMonitorStateException("Lock count has gone negative for lock: " + basePath);
    }
    try {
      internals.releaseLock(lockData.lockPath);
    } finally {
      threadData.remove(currentThread);
    }
  }
 @Override
 public void makeRevocable(
     final RevocationListener<InterProcessMutex> listener, Executor executor) {
   internals.makeRevocable(
       new RevocationSpec(
           executor,
           new Runnable() {
             @Override
             public void run() {
               listener.revocationRequested(InterProcessMutex.this);
             }
           }));
 }
  private boolean internalLock(long time, TimeUnit unit) throws Exception {
    /*
       Note on concurrency: a given lockData instance
       can be only acted on by a single thread so locking isn't necessary
    */

    Thread currentThread = Thread.currentThread();

    LockData lockData = threadData.get(currentThread);
    if (lockData != null) {
      // re-entering
      lockData.lockCount.incrementAndGet();
      return true;
    }

    String lockPath = internals.attemptLock(time, unit, getLockNodeBytes());
    if (lockPath != null) {
      LockData newLockData = new LockData(currentThread, lockPath);
      threadData.put(currentThread, newLockData);
      return true;
    }

    return false;
  }
 /**
  * Return a sorted list of all current nodes participating in the lock
  *
  * @return list of nodes
  * @throws Exception ZK errors, interruptions, etc.
  */
 public Collection<String> getParticipantNodes() throws Exception {
   return LockInternals.getParticipantNodes(
       internals.getClient(), basePath, internals.getLockName(), internals.getDriver());
 }