getAndSet()方法,解锁操作,是一个并发操作。

来源:13-8 redis分布式锁

我弟是个程序员

2019-03-26

在死锁的情况下,如果有两个用户(A和B)一前(A)一后(B)执行了解锁操作。
由于getAndSet()方法解锁操作是一个并发操作,结果当然是先解锁的A用户获得了锁资格。但是,解锁的时候,由于另一个未获得锁的用户B由于后也执行了getset操作,导致,key的value值已经被修改了,那么这个时候就会导致A解锁失败了。从而又再次进入死锁。是不是会产生问题???

写回答

4回答

我弟是个程序员

提问者

2019-03-28

 public boolean lock(String key, String value) {
       
        if(redisTemplate.opsForValue().setIfAbsent(key, value)) {
            return true;
        }
       
        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)) {
                /**  校验value值*/
                String doubleCheckValue = redisTemplate.opsForValue().get(key);
                if (!StringUtils.isEmpty(doubleCheckValue) && !doubleCheckValue.equals(value)) {
                    redisTemplate.opsForValue().set(key,value);
                }
                return true;
            }
        }
        
        return false;
    }

你好,我修改了一点点加锁的代码,测试发现貌似解决了持续死锁的问题,您能帮我分析下,会不会是我看错了吗?

0
1
廖师兄
除开死锁,还有其他的问题要解决 https://mp.weixin.qq.com/s/8fdBKAyHZrfHmSajXT_dnA
2019-03-29
共1条回复

我弟是个程序员

提问者

2019-03-27

我测试了下,这个方法,不能出现超时情况,超时情况下,持续高并发下,会导致解锁操作失败,从而持续死锁。。。

0
1
廖师兄
课程中的redis锁的确有些问题,redis锁原理以及需要处理的细节问题可以看 https://mp.weixin.qq.com/s/8fdBKAyHZrfHmSajXT_dnA 推荐使用这个rediss分布式锁 https://github.com/redisson/redisson/tree/master/redisson-spring-boot-starter
2019-03-27
共1条回复

我弟是个程序员

提问者

2019-03-27

虽然最终只有一个客户端可以加锁,但是这个客户端的锁的过期时间可能被其他客户端覆盖。

0
0

廖师兄

2019-03-26

”getAndSet()方法解锁操作是一个并发操作“ 这是单线程的,redis实现的。

0
0

Spring Boot双版本(1.5/2.1) 打造企业级微信点餐系统

从0到1开发中小型企业级Java应用,并学会迭代重构技巧

6410 学习 · 5247 问题

查看课程