采纳答案成功!
向帮助你的同学说点啥吧!感谢那些助人为乐的人
视频中分布式锁lock函数的上锁逻辑是如果发现key过期,则先做一次get再做一次getandset,然后比较两个的返回值一不一样来判断是否取到锁。如果两个线程竞争,两个线程都会调用getandset,那对于没取到锁的线程依然会调用了getandset,那redis里面的值不就被改变了吗(如果被改变,那获得锁的线程在解锁时不就也会失败吗),请问这里怎么保证取锁失败的线程,在调用getandset后不会影响程序的正常进行?
是的,这块有bug,就是第二个线程只要跟第一个线程的毫秒不完全一样,那么第二个线程在执行getandset以后会导致解锁失败,从而造成死锁,很明显了已经。
同样的疑问,这块逻辑有问题!第二个线程getAndSet()之后虽然会加锁失败,但是会改变当前的value,导致第一个线程无法解锁!
而且这里其实还有一个问题,假如我有三个线程A,B,C同时发现了过期并尝试竞争锁,第一个A获得了锁并且更新redis中的值为a,第二个B发现旧的值不等于新的值,但是也更新redis中的值,此时为b,B更新完了以后C才做get + getset的操作,C会发现get取到的是b并且getset也取到的是b,他就认为自己拿到锁了,那这样其实A拿到了锁在扣库存,C也拿到了锁在扣库存,这不会超卖吗
好久没登陆了。刚看了下你的逻辑,确实也会发生超卖的问题。廖师兄这块逻辑本身就不对,说句题外话,这门课和微服务没任何关系,不知道为啥题目有个微服务
你的意思就是,一个currenttime只有一个线程操作吧,那样效率太低了。
不太明白你的意思。你可否用实例代码来说明
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和自己设置的不一样,就无法正常解锁,这个问题可以帮我解答一下吗
登录后可查看更多问答,登录/注册
从0到1开发中小型企业级Java应用,并学会迭代重构技巧
8.3k 10
3.3k 4
6.8k 9
2.0k 32
4.1k 26