上一篇文章:java | 基于Redis的分布式锁实现①
是基于jedis
组件实现的分布式锁。这篇不借用组件,直接使用StringRedisTemplate
实现
加锁
@Autowired
private StringRedisTemplate stringRedisTemplate;
/***
* 加锁
* @param key
* @param value 当前时间+超时时间
* @return 锁住返回true
*/
public boolean lock(String key, String value) {
//1 key对应的锁不存在,加锁成功
if (Boolean.TRUE.equals(stringRedisTemplate.opsForValue().setIfAbsent(key, value))) {
log.info(key + " 加锁成功");
return true;
}
//2.1 锁存在,获取锁的对应的值(超时时间)。
String lockValue = stringRedisTemplate.opsForValue().get(key);
//2.2 如果值比当前时间要小的话,说明该锁已经超时。重新设置超时时间
if (!StringUtils.isEmpty(lockValue) && Long.parseLong(lockValue) < System.currentTimeMillis()) {
//getAndSet(key,value)线程阻塞(某一时刻一定只有一个线程执行这个方法,其他要等待)
//getAndSet(key,value) 首先会GET到当前key的值并返回,然后设置当前Key值为要设置的新Value
String oldLockValue = stringRedisTemplate.opsForValue().getAndSet(key, value);
String newLockValue = stringRedisTemplate.opsForValue().get(key);
//3 如果通过getSet返回的时间和之前通过get获取到的时间一样的,并且key对应的新value与要设置的value一直,则说明加锁成功了。
if (!StringUtils.isEmpty(oldLockValue) && oldLockValue.equals(lockValue) && value.equals(newLockValue)) {
log.info(key + " 加锁成功");
return true;
}
}
//2.3 key对应的锁已存在,且未超时,加锁失败。
log.error(key + " 加锁失败");
return false;
}
解锁
/***
* 解锁
* @param key
* @param value
* @return
*/
public void unlock(String key, String value) {
try {
String currentValue = stringRedisTemplate.opsForValue().get(key);
System.out.println("currentValue:" + currentValue);
if (!StringUtils.isEmpty(currentValue) && currentValue.equals(value)) {
stringRedisTemplate.opsForValue().getOperations().delete(key);
}
} catch (Exception e) {
log.error(key + "解锁失败:" + e.getMessage());
}
}
具体实现就不解释了,代码注释都有