Fixed - Incorrect RedissonRedLock.tryLock behaviour (backported)

2.2.x
Nikita 9 years ago
parent 471c927e04
commit bce896d47b

@ -19,6 +19,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.ListIterator;
import java.util.List;
import java.util.Map;
import java.util.Queue;
@ -188,36 +189,12 @@ public class RedissonMultiLock implements Lock {
@Override
public boolean tryLock() {
Map<RLock, Future<Boolean>> tryLockFutures = new HashMap<RLock, Future<Boolean>>(locks.size());
for (RLock lock : locks) {
tryLockFutures.put(lock, lock.tryLockAsync());
}
return sync(tryLockFutures);
}
protected boolean sync(Map<RLock, Future<Boolean>> tryLockFutures) {
List<RLock> lockedLocks = new ArrayList<RLock>(tryLockFutures.size());
RuntimeException latestException = null;
for (Entry<RLock, Future<Boolean>> entry : tryLockFutures.entrySet()) {
try {
if (entry.getValue().syncUninterruptibly().getNow()) {
lockedLocks.add(entry.getKey());
}
} catch (RuntimeException e) {
latestException = e;
}
}
if (lockedLocks.size() < tryLockFutures.size()) {
unlockInner(lockedLocks);
if (latestException != null) {
throw latestException;
}
try {
return tryLock(-1, -1, null);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
return true;
}
protected void unlockInner(Collection<RLock> locks) {
@ -235,14 +212,70 @@ public class RedissonMultiLock implements Lock {
public boolean tryLock(long waitTime, TimeUnit unit) throws InterruptedException {
return tryLock(waitTime, -1, unit);
}
protected int failedLocksLimit() {
return 1;
}
public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
Map<RLock, Future<Boolean>> tryLockFutures = new HashMap<RLock, Future<Boolean>>(locks.size());
for (RLock lock : locks) {
tryLockFutures.put(lock, lock.tryLockAsync(waitTime, leaseTime, unit));
long newLeaseTime = -1;
if (leaseTime != -1) {
newLeaseTime = waitTime*2;
}
long time = System.currentTimeMillis();
long remainTime = -1;
if (waitTime != -1) {
remainTime = unit.toMillis(waitTime);
}
int failedLocksLimit = failedLocksLimit();
List<RLock> lockedLocks = new ArrayList<RLock>(locks.size());
for (ListIterator<RLock> iterator = locks.listIterator(); iterator.hasNext();) {
RLock lock = iterator.next();
boolean lockAcquired;
if (waitTime == -1 && leaseTime == -1) {
lockAcquired = lock.tryLock();
} else {
lockAcquired = lock.tryLock(unit.convert(remainTime, TimeUnit.MILLISECONDS), newLeaseTime, unit);
}
if (lockAcquired) {
lockedLocks.add(lock);
} else {
failedLocksLimit--;
if (failedLocksLimit == 0) {
unlockInner(lockedLocks);
if (waitTime == -1 && leaseTime == -1) {
return false;
}
failedLocksLimit = failedLocksLimit();
lockedLocks.clear();
}
}
if (remainTime != -1) {
remainTime -= (System.currentTimeMillis() - time);
time = System.currentTimeMillis();
if (remainTime < 0) {
unlockInner(lockedLocks);
return false;
}
}
}
return sync(tryLockFutures);
if (leaseTime != -1) {
List<Future<Boolean>> futures = new ArrayList<Future<Boolean>>(lockedLocks.size());
for (RLock rLock : lockedLocks) {
Future<Boolean> future = rLock.expireAsync(unit.toMillis(leaseTime), TimeUnit.MILLISECONDS);
futures.add(future);
}
for (Future<Boolean> rFuture : futures) {
rFuture.syncUninterruptibly();
}
}
return true;
}
@ -259,7 +292,6 @@ public class RedissonMultiLock implements Lock {
}
}
@Override
public Condition newCondition() {
throw new UnsupportedOperationException();

@ -45,28 +45,9 @@ public class RedissonRedLock extends RedissonMultiLock {
super(locks);
}
protected boolean sync(Map<RLock, Future<Boolean>> tryLockFutures) {
List<RLock> lockedLocks = new ArrayList<RLock>(tryLockFutures.size());
RuntimeException latestException = null;
for (Entry<RLock, Future<Boolean>> entry : tryLockFutures.entrySet()) {
try {
if (entry.getValue().syncUninterruptibly().getNow()) {
lockedLocks.add(entry.getKey());
}
} catch (RuntimeException e) {
latestException = e;
}
}
if (lockedLocks.size() < minLocksAmount(locks)) {
unlockInner(lockedLocks);
if (latestException != null) {
throw latestException;
}
return false;
}
return true;
@Override
protected int failedLocksLimit() {
return locks.size() - minLocksAmount(locks);
}
protected int minLocksAmount(final List<RLock> locks) {

Loading…
Cancel
Save