java | 基于Redis的分布式锁实现②

该篇文章介绍了如何在Java中不依赖组件,直接使用SpringDataRedis的StringRedisTemplate实现分布式锁。主要方法包括setIfAbsent进行加锁尝试,以及通过getAndSet检查并更新锁的超时时间来确保锁的安全性。解锁过程则是对比锁的值并删除键。
摘要由CSDN通过智能技术生成

上一篇文章: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());
        }
    }

具体实现就不解释了,代码注释都有

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值