请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

Redis分布式锁中getSet方法疑问

Redis分布式锁中,当锁过期的时候,如果多个客户端同时执行getSet()方法,那么虽然最终只有一个线程可以加锁,但是这个线程的锁的过期时间可能被其线程覆盖。

比如key的时间是10000,线程A的过期时间是10010,线程B的过期时间是10020。当线程A执行了getSet方法拿到了锁,那么key里面的值为10010,然后线程B也去抢锁,执行getSet方法,虽然返回的值是10010,与B线程的锁的过期时间不等,B拿不到锁,但是,此时key的值被线程B改为10020了。  这个情况怎么办?


正在回答 回答被采纳积分+3

1回答

廖师兄 2018-04-10 23:44:38

"比如key的时间是10000,线程A的过期时间是10010"  ,不太明白你的意思,可否直接拿课程中redis锁的代码来说明呢


-------更新----------

但此时key的value变成了10020, 但是返回的是10010。 你看看这边文章前面部分的文字说明 https://blog.csdn.net/abbc7758521/article/details/77990048 , 结合我给的代码(下方) 

/**
 * 加锁
 * @param key
 * @param value 当前时间+超时时间
 * @return
 */
public boolean lock(String key, String value) {
    if(redisTemplate.opsForValue().setIfAbsent(key, value)) {
        return true;
    }
    //currentValue=A   这两个线程的value都是B  其中一个线程拿到锁
    String currentValue = redisTemplate.opsForValue().get(key);
    //如果锁过期
    if (!StringUtils.isEmpty(currentValue)
            && Long.parseLong(currentValue) < System.currentTimeMillis()) {
        //获取上一个锁的时间
        String oldValue = redisTemplate.opsForValue().getAndSet(key, value);
        if (!StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue)) {
            return true;
        }
    }

    return false;
}


0 回复 有任何疑惑可以回复我~
  • 师兄你好,这位同学的意思是假设两个线程,过期锁的value为10000,线程A的value为10010,B的value为10020,如果A先拿到锁,getSet后,oldValue=10010,然后B也想去加锁执行getSet发现加锁不了,但此时key的value变成了10020,那B再想去加锁怎么加?我的理解是如果按照前面说的那么执行,B再去加锁,currentValue = get(key)应该是=10020了吧,然后下面的getSet也=10020,B加锁成功,是这样的吗师兄?
    回复 有任何疑惑可以回复我~ 2018-04-14 17:05:05
  • 但此时key的value变成了10020, 但是返回的是10010。
    你看看这边文章前面部分的文字说明 https://blog.csdn.net/abbc7758521/article/details/77990048 , 结合我给的代码(下方) 
    
        /**
         * 加锁
         * @param key
         * @param value 当前时间+超时时间
         * @return
         */
        public boolean lock(String key, String value) {
            if(redisTemplate.opsForValue().setIfAbsent(key, value)) {
                return true;
            }
            //currentValue=A   这两个线程的value都是B  其中一个线程拿到锁
            String currentValue = redisTemplate.opsForValue().get(key);
            //如果锁过期
            if (!StringUtils.isEmpty(currentValue)
                    && Long.parseLong(currentValue) < System.currentTimeMillis()) {
                //获取上一个锁的时间
                String oldValue = redisTemplate.opsForValue().getAndSet(key, value);
                if (!StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue)) {
                    return true;
                }
            }
    
            return false;
        }
    回复 有任何疑惑可以回复我~ 2018-04-16 00:38:24
  • 师兄,那三个命令我是懂了,我就是有一点疑惑的两个线程A,B,如果A先加了锁,B要加锁的话,是不是一定要等A处理完解锁后才能加锁呢?
    回复 有任何疑惑可以回复我~ 2018-04-17 00:01:23
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信