redis 分布式多线程细粒度锁

来源:互联网 发布:达内培训 php机构 编辑:程序博客网 时间:2024/06/01 09:18
@Autowiredprivate 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);    }}