基于redis实现的分布式锁
import org.springframework.data.redis.core.RedisTemplate;
public class RedisLock {
private RedisTemplate redisTemplate;
private static final ThreadLocal<String> tlExpireTime = new ThreadLocal<>();
private static final long WAIT_TIME_OUT = 10 * 1000;
private static final int LOCK_EXPIRE_TIME = 3 * 1000;
public RedisLock(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
public Boolean lock(String key) throws InterruptedException {
long timeOut = WAIT_TIME_OUT;
while (timeOut > 0) {
long expireTime = System.currentTimeMillis() + LOCK_EXPIRE_TIME;
Boolean isExists = redisTemplate.boundValueOps(key).setIfAbsent(expireTime);
if (isExists) {
tlExpireTime.set(expireTime+"");
return true;
}
long oldExpireTime = (long) redisTemplate.boundValueOps(key).get();
if (oldExpireTime < System.currentTimeMillis()) {
long newExpireTime = System.currentTimeMillis() + LOCK_EXPIRE_TIME;
long oldExpireTime2 = (long) redisTemplate.boundValueOps(key).getAndSet(newExpireTime);
if (oldExpireTime == oldExpireTime2) {
tlExpireTime.set(newExpireTime+"");
return true;
}
}
long sleepTime = (long) (Math.random() * 1000);
timeOut = timeOut - sleepTime;
Thread.sleep(sleepTime);
}
return false;
}
public void unlock(String key) {
long expireTimeMillis = (long) redisTemplate.boundValueOps(key).get();
String strExpireTime = tlExpireTime.get();
if (strExpireTime != null && strExpireTime.length() > 0) {
long oldExpireTime = Long.parseLong(strExpireTime);
if ((System.currentTimeMillis() < oldExpireTime) || (oldExpireTime == expireTimeMillis)) {
redisTemplate.delete(key);
}
}
tlExpireTime.remove();
}
}