diff --git a/redisson/src/main/java/org/redisson/RedissonSpinLock.java b/redisson/src/main/java/org/redisson/RedissonSpinLock.java index 4299af0d9..a7786dcf5 100644 --- a/redisson/src/main/java/org/redisson/RedissonSpinLock.java +++ b/redisson/src/main/java/org/redisson/RedissonSpinLock.java @@ -27,7 +27,6 @@ import java.util.Collections; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; /** * Distributed implementation of {@link java.util.concurrent.locks.Lock} @@ -145,31 +144,28 @@ public class RedissonSpinLock extends RedissonBaseLock { @Override public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException { - long time = unit.toMillis(waitTime); - long current = System.currentTimeMillis(); - long threadId = Thread.currentThread().getId(); + final long time = unit.toMillis(waitTime); + final long current = System.currentTimeMillis(); + final long threadId = Thread.currentThread().getId(); Long ttl = tryAcquire(leaseTime, unit, threadId); // lock acquired if (ttl == null) { return true; } - time -= System.currentTimeMillis() - current; - if (time <= 0) { + if (System.currentTimeMillis() - current >= time) { acquireFailed(waitTime, unit, threadId); return false; } LockOptions.BackOffPolicy backOffPolicy = backOff.create(); while (true) { - current = System.currentTimeMillis(); Thread.sleep(backOffPolicy.getNextSleepPeriod()); ttl = tryAcquire(leaseTime, unit, threadId); if (ttl == null) { return true; } - time -= System.currentTimeMillis() - current; - if (time <= 0) { + if (System.currentTimeMillis() - current >= time) { acquireFailed(waitTime, unit, threadId); return false; } @@ -262,16 +258,14 @@ public class RedissonSpinLock extends RedissonBaseLock { long currentThreadId) { CompletableFuture result = new CompletableFuture<>(); - AtomicLong time = new AtomicLong(unit.toMillis(waitTime)); LockOptions.BackOffPolicy backOffPolicy = backOff.create(); - tryLock(leaseTime, unit, currentThreadId, result, time, backOffPolicy); + tryLock(System.currentTimeMillis(), leaseTime, unit, currentThreadId, result, unit.toMillis(waitTime), backOffPolicy); return new CompletableFutureWrapper<>(result); } - private void tryLock(long leaseTime, TimeUnit unit, long currentThreadId, CompletableFuture result, - AtomicLong time, LockOptions.BackOffPolicy backOffPolicy) { - long startTime = System.currentTimeMillis(); + private void tryLock(long startTime, long leaseTime, TimeUnit unit, long currentThreadId, CompletableFuture result, + long waitTime, LockOptions.BackOffPolicy backOffPolicy) { RFuture ttlFuture = tryAcquireAsync(leaseTime, unit, currentThreadId); ttlFuture.whenComplete((ttl, e) -> { if (e != null) { @@ -287,17 +281,14 @@ public class RedissonSpinLock extends RedissonBaseLock { return; } - long el = System.currentTimeMillis() - startTime; - time.addAndGet(-el); - - if (time.get() <= 0) { + if (System.currentTimeMillis() - startTime >= waitTime) { trySuccessFalse(currentThreadId, result); return; } long nextSleepPeriod = backOffPolicy.getNextSleepPeriod(); getServiceManager().newTimeout( - timeout -> tryLock(leaseTime, unit, currentThreadId, result, time, backOffPolicy), + timeout -> tryLock(startTime, leaseTime, unit, currentThreadId, result, waitTime, backOffPolicy), nextSleepPeriod, TimeUnit.MILLISECONDS); }); } diff --git a/redisson/src/test/java/org/redisson/RedissonSpinLockTest.java b/redisson/src/test/java/org/redisson/RedissonSpinLockTest.java index 36e0800f7..cee8c96bd 100644 --- a/redisson/src/test/java/org/redisson/RedissonSpinLockTest.java +++ b/redisson/src/test/java/org/redisson/RedissonSpinLockTest.java @@ -473,6 +473,27 @@ public class RedissonSpinLockTest extends BaseConcurrentTest { } + @Test + public void testTryLockAsyncWaitTime() throws InterruptedException { + RLock lock = redisson.getSpinLock("lock"); + lock.lock(); + + AtomicBoolean lockAsyncSucceed = new AtomicBoolean(true); + Thread thread = new Thread(() -> { + RFuture booleanRFuture = lock.tryLockAsync(1, 30, TimeUnit.SECONDS); + booleanRFuture.whenComplete((res, e) -> { + if (e != null) { + Assertions.fail("Lock aquire failed for some reason"); + } + lockAsyncSucceed.set(res); + }); + }); + thread.start(); + Thread.sleep(1500); + assertThat(lockAsyncSucceed.get()).isFalse(); + lock.forceUnlock(); + } + @Test public void testTryLockAsyncFailed() throws InterruptedException { RLock lock = redisson.getSpinLock("lock");