public Entry tryLockEntry(long id, long time) throws IOException {
    Preconditions.checkArgument(time >= 0);
    Thread currentThread = Thread.currentThread();
    Entry entry = new Entry(id, currentThread);
    Entry existing;
    long waitUtilTS = EnvironmentEdgeManager.currentTime() + time;
    long remaining = time;
    while ((existing = map.putIfAbsent(entry.id, entry)) != null) {
      synchronized (existing) {
        if (existing.locked) {
          ++existing.numWaiters; // Add ourselves to waiters.
          try {
            while (existing.locked) {
              existing.wait(remaining);
              if (existing.locked) {
                long currentTS = EnvironmentEdgeManager.currentTime();
                if (currentTS >= waitUtilTS) {
                  // time is up
                  return null;
                } else {
                  // our wait is waken, but the lock is still taken, this can happen
                  // due to JDK Object's wait/notify mechanism.
                  // Calculate the new remaining time to wait
                  remaining = waitUtilTS - currentTS;
                }
              }

            }
          } catch (InterruptedException e) {
            // HBASE-21292
            // Please refer to the comments in getLockEntry()
            // the difference here is that we decrease numWaiters in finally block
            if (!existing.locked && existing.numWaiters == 1) {
              map.remove(existing.id);
            }
            throw new InterruptedIOException("Interrupted waiting to acquire sparse lock");
          } finally {
            --existing.numWaiters; // Remove ourselves from waiters.
          }
          existing.locked = true;
          existing.holder = currentThread;
          return existing;
        }
        // If the entry is not locked, it might already be deleted from the
        // map, so we cannot return it. We need to get our entry into the map
        // or get someone else's locked entry.
      }
    }
    return entry;
  }
Blocks until the lock corresponding to the given id is acquired.
@param id   an arbitrary number to lock on
@param time time to wait in ms
@return an "entry" to pass to {@link #releaseLockEntry(Entry)} to release the lock
@throws IOException if interrupted
hbase-common/src/main/java/org/apache/hadoop/hbase/util/IdLock.java