Fixed - RedissonRedLock couldn't be locked in some cases. #1175

pull/1204/head
Nikita 7 years ago
parent b9d9f87043
commit b4cc6f9941

@ -75,18 +75,19 @@ public class RedissonMultiLock implements Lock {
} }
public void lockInterruptibly(long leaseTime, TimeUnit unit) throws InterruptedException { public void lockInterruptibly(long leaseTime, TimeUnit unit) throws InterruptedException {
long baseWaitTime = locks.size() * 1500;
long waitTime = -1; long waitTime = -1;
if (leaseTime == -1) { if (leaseTime == -1) {
waitTime = 5; waitTime = baseWaitTime;
unit = TimeUnit.SECONDS; unit = TimeUnit.MILLISECONDS;
} else { } else {
waitTime = unit.toMillis(leaseTime); waitTime = unit.toMillis(leaseTime);
if (waitTime <= 2000) { if (waitTime <= 2000) {
waitTime = 2000; waitTime = 2000;
} else if (waitTime <= 5000) { } else if (waitTime <= baseWaitTime) {
waitTime = ThreadLocalRandom.current().nextLong(waitTime/2, waitTime); waitTime = ThreadLocalRandom.current().nextLong(waitTime/2, waitTime);
} else { } else {
waitTime = ThreadLocalRandom.current().nextLong(5000, waitTime); waitTime = ThreadLocalRandom.current().nextLong(baseWaitTime, waitTime);
} }
waitTime = unit.convert(waitTime, TimeUnit.MILLISECONDS); waitTime = unit.convert(waitTime, TimeUnit.MILLISECONDS);
} }
@ -131,7 +132,7 @@ public class RedissonMultiLock implements Lock {
public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException { public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
long newLeaseTime = -1; long newLeaseTime = -1;
if (leaseTime != -1) { if (leaseTime != -1) {
newLeaseTime = waitTime*2; newLeaseTime = unit.toMillis(waitTime)*2;
} }
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
@ -139,6 +140,8 @@ public class RedissonMultiLock implements Lock {
if (waitTime != -1) { if (waitTime != -1) {
remainTime = unit.toMillis(waitTime); remainTime = unit.toMillis(waitTime);
} }
long lockWaitTime = calcLockWaitTime(remainTime);
int failedLocksLimit = failedLocksLimit(); int failedLocksLimit = failedLocksLimit();
List<RLock> lockedLocks = new ArrayList<RLock>(locks.size()); List<RLock> lockedLocks = new ArrayList<RLock>(locks.size());
for (ListIterator<RLock> iterator = locks.listIterator(); iterator.hasNext();) { for (ListIterator<RLock> iterator = locks.listIterator(); iterator.hasNext();) {
@ -148,8 +151,8 @@ public class RedissonMultiLock implements Lock {
if (waitTime == -1 && leaseTime == -1) { if (waitTime == -1 && leaseTime == -1) {
lockAcquired = lock.tryLock(); lockAcquired = lock.tryLock();
} else { } else {
long awaitTime = unit.convert(remainTime, TimeUnit.MILLISECONDS); long awaitTime = Math.min(lockWaitTime, remainTime);
lockAcquired = lock.tryLock(awaitTime, newLeaseTime, unit); lockAcquired = lock.tryLock(awaitTime, newLeaseTime, TimeUnit.MILLISECONDS);
} }
} catch (Exception e) { } catch (Exception e) {
lockAcquired = false; lockAcquired = false;
@ -203,6 +206,9 @@ public class RedissonMultiLock implements Lock {
return true; return true;
} }
protected long calcLockWaitTime(long remainTime) {
return remainTime;
}
@Override @Override
public void unlock() { public void unlock() {

@ -170,9 +170,21 @@ public class RedissonRedLockTest {
RLock lock2 = client1.getLock("lock2"); RLock lock2 = client1.getLock("lock2");
RLock lock3 = client2.getLock("lock3"); RLock lock3 = client2.getLock("lock3");
testLock(lock1, lock2, lock3, lock1);
testLock(lock1, lock2, lock3, lock2);
testLock(lock1, lock2, lock3, lock3);
client1.shutdown();
client2.shutdown();
assertThat(redis1.stop()).isEqualTo(0);
assertThat(redis2.stop()).isEqualTo(0);
}
protected void testLock(RLock lock1, RLock lock2, RLock lock3, RLock lockFirst) throws InterruptedException {
Thread t1 = new Thread() { Thread t1 = new Thread() {
public void run() { public void run() {
lock3.lock(); lockFirst.lock();
}; };
}; };
t1.start(); t1.start();
@ -193,17 +205,11 @@ public class RedissonRedLockTest {
t.start(); t.start();
t.join(1000); t.join(1000);
lock3.delete(); lockFirst.delete();
RedissonMultiLock lock = new RedissonRedLock(lock1, lock2, lock3); RedissonMultiLock lock = new RedissonRedLock(lock1, lock2, lock3);
lock.lock(); lock.lock();
lock.unlock(); lock.unlock();
client1.shutdown();
client2.shutdown();
assertThat(redis1.stop()).isEqualTo(0);
assertThat(redis2.stop()).isEqualTo(0);
} }

Loading…
Cancel
Save