@Autowired
private StringRedisTemplate redisTemplate;
加锁
/**
*
* @param key
* @param value 一般用 当前时间+超时时间
* @return
*/
public boolean lock(String key,String value){
if(redisTemplate.opsForValue().setIfAbsent(key,value)){
//没有线程获得这个key的锁
return true;
}
// 即使锁被占用,再判断锁是否过期
String currentValue = redisTemplate.opsForValue().get(key);
if(!StringUtils.isEmpty(currentValue) &&
Long.parseLong(currentValue) < System.currentTimeMillis()){
// 锁过期,再判断是否有两个线程都走到了这里,还是有锁的原子性问题.
//利用了Redis操作的原子性。该方法是原子操作。所以后一个线程执行该方法是在前一个线程已经设置好value并且返回给oldValue之后
// 这样第一个进来的线程是可以返回true。后面的都不可以。
// 所以理论上value值是不能有重复的。
String oldValue = redisTemplate.opsForValue().getAndSet(key,value);
if(!StringUtils.isEmpty(oldValue) && oldValue.equals(value)){
return true;
}
}
return false;
}
解锁
public void unlock(String key,String value){
String currentValue = redisTemplate.opsForValue().get(key);
if(!StringUtils.isEmpty(currentValue) && currentValue.equals(value)){
redisTemplate.opsForValue().getOperations().delete(key);
}
}