private final static int INIT_VERSION = 2;
/**
* 单位为毫秒; 获取的锁的自动释放时间是100ms.
*/
private final static int DEFAULT_EXPIRE_TIME = 100;
/**
* 单位为毫秒; 获取锁时, 默认的等待时间. 重试次数计算: DEFAULT_TIMEOUT/DEFAULT_LOCK_RETRY_INTERVAL
*/
private final static int DEFAULT_TIMEOUT = 200;
/**
* 单位为毫秒; 获取锁时, 默认重试的时间间隔是50ms.
*/
private final static int DEFAULT_LOCK_RETRY_INTERVAL = 50;
/**
* 释放锁时, 默认进行五次重试.
*/
private final static int DEFAULT_UNLOCK_RETRY_COUNT = 5;
private ThreadLocal<String> threadValue = new ThreadLocal<String>();
@Override
public boolean lock(String key) {
return lock(key, DEFAULT_EXPIRE_TIME, DEFAULT_TIMEOUT);
}
@Override
public boolean lock(String key, int expireTime, long timeout) {
long start = System.currentTimeMillis();
for (; ; ) {
boolean rs = tryLock(key, expireTime);
if (rs) {
return true;
}
long current = System.currentTimeMillis();
if ((current - start + DEFAULT_LOCK_RETRY_INTERVAL) > timeout) {
LOG.error("lock timeout. key:{}", key);
return false;
}
waitToRetry();
}
}
@Override
public boolean tryLock(String key, int expireTime) {
try {
DataEntry<String> dataEntry = super.get(key);
// 如果已经有值, 则判断是否是重入场景
if (dataEntry != null && !StringUtils.isBlank(dataEntry.getValue())) {
String value = dataEntry.getValue();
return threadValue.get() != null && threadValue.get().equals(value);
}
// 如果没有值, 则设置值, 获取锁
String value = threadValue.get();
if (value == null) {
value = generateValue();
threadValue.set(value);
}
super.setWithVersion(key, value, INIT_VERSION, expireTime);
return true;
} catch (Exception e) {
LOG.error("tryLock error. key:{}", key, e);
return false;
}
}
@Override
public boolean unlock(String key) {
String value = threadValue.get();
for (int i = 0; i < DEFAULT_UNLOCK_RETRY_COUNT; i++) {
try {
DataEntry<String> stringDataEntry = super.get(key);
if (null != stringDataEntry && StringUtils.isNotBlank(
stringDataEntry.getValue()) && StringUtils.isNotBlank(value) && StringUtils.equals(
stringDataEntry.getValue(), value)) {
super.remove(key);
threadValue.remove();
return true;
} else {
LOG.error("unlock error. key:{}", key);
return false;
}
} catch (Exception e) {
LOG.error("unlock error. key:{}", key, e);
}
}
LOG.error("unlock fail after retry ${} times, tair service may be unavailable now", DEFAULT_UNLOCK_RETRY_COUNT);
return false;
}
private void waitToRetry() {
try {
Thread.sleep(DEFAULT_LOCK_RETRY_INTERVAL);
} catch (Exception e) {
LOG.warn("waitToRetry error", e);
}
}
private String generateValue() {
return Thread.currentThread().getName() + "_" + UUID.randomUUID().toString();
}