Redis分布式锁过期时间的疑问

来源:13-8 redis分布式锁

慕娘83406391

2021-07-26

视频中分布式锁lock函数的上锁逻辑是如果发现key过期,则先做一次get再做一次getandset,然后比较两个的返回值一不一样来判断是否取到锁。如果两个线程竞争,两个线程都会调用getandset,那对于没取到锁的线程依然会调用了getandset,那redis里面的值不就被改变了吗(如果被改变,那获得锁的线程在解锁时不就也会失败吗),请问这里怎么保证取锁失败的线程,在调用getandset后不会影响程序的正常进行?

写回答

3回答

慕尼黑5723975

2022-04-11

是的,这块有bug,就是第二个线程只要跟第一个线程的毫秒不完全一样,那么第二个线程在执行getandset以后会导致解锁失败,从而造成死锁,很明显了已经。

1
0

心死则忙

2021-08-02

同样的疑问,这块逻辑有问题!第二个线程getAndSet()之后虽然会加锁失败,但是会改变当前的value,导致第一个线程无法解锁!

0
2
心死则忙
回复
慕娘83406391
好久没登陆了。刚看了下你的逻辑,确实也会发生超卖的问题。廖师兄这块逻辑本身就不对,说句题外话,这门课和微服务没任何关系,不知道为啥题目有个微服务
2021-08-22
共2条回复

廖师兄

2021-07-26

  1. 你的意思就是,一个currenttime只有一个线程操作吧,那样效率太低了。

  2. 不太明白你的意思。你可否用实例代码来说明

0
1
慕娘83406391
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; } currenttime那个是我理解有问题。咱们只讨论另一个问题,我现在想知道A,B两个线程,他们都同时发现之前的锁过期了,于是开始竞争锁,那他们无论谁获取到锁,都会调用getandset,只不过没有取到锁的线程这个函数会返回false,但是它依然掉用了getandset,就也改变了redis的值,那对于竞争到锁的线程,在解锁时会发现value和自己设置的不一样,就无法正常解锁,这个问题可以帮我解答一下吗
2021-07-26
共1条回复

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

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

6410 学习 · 5247 问题

查看课程