public boolean tryLock(final byte[] ctx, final long timeout, final TimeUnit unit) {
        final long timeoutNs = unit.toNanos(timeout);
        final long startNs = System.nanoTime();
        int attempts = 1;
        try {
            for (;;) {
                final Owner owner = internalTryLock(ctx);
                if (owner.isSuccess()) {
                    return true;
                }
                if (System.nanoTime() - startNs >= timeoutNs) {
                    break;
                }
                if (attempts < 8) {
                    attempts++;
                }
                final long remaining = Math.max(0, owner.getRemainingMillis());
                // TODO optimize with notify?
                // avoid liveLock
                Thread.sleep(Math.min(remaining, 2 << attempts));
            }
        } catch (final Throwable t) {
            ThrowUtil.throwException(t);
        }
        return false;
    }
Acquires the lock if it is free within the given waiting time.

If the lock is available this method returns immediately
with the value {@code true}.
If the lock is not available then
the current thread becomes disabled for thread scheduling
purposes and lies dormant until one of two things happens:
<ul>
<li>The lock is acquired by the current thread; or
<li>The specified waiting time elapses

@param ctx     the context of current lock request
@param timeout the maximum time to wait for the lock
@param unit    the time unit of the {@code time} argument
@return {@code true} if the lock was acquired and {@code false}
if the waiting time elapsed before the lock was acquired
jraft-rheakv/rheakv-core/src/main/java/com/alipay/sofa/jraft/rhea/util/concurrent/DistributedLock.java