【Redis】分布式锁的原子性问题

更为极端的误删逻辑说明:

同样的是redis锁的一个周期,然后下面是一个线程

image-20240528181454032

同样的是线程1一上来就申请锁,线程1现在持有锁之后,在执行业务逻辑过程中,他正准备删除锁,而且已经走到了判断锁标识的过程中,由于这把锁是自己的,因此肯定返回ok,紧接着就要执行释放锁的动作了。这里要注意的是判断锁标识和释放锁是两个动作,判断是成功的,正准备删除锁,产生了阻塞。JVM中有一个东西叫做垃圾回收,当我们JVM去做这种GC的时候,它其实是会阻塞我们所有的代码,因此此时就会产生阻塞。不是因为你的业务阻塞,而是因为JVM本身产生阻塞,是有这种可能性的。

一旦发生了阻塞,并且这个阻塞的时间如果足够长,就有可能触发锁的超时释放。

image-20240528182101033

锁一旦超时释放,其他的线程又可以乘虚而入了,例如此时线程2进来,由于锁被释放掉了,因此它可以继续获取锁,可以开始执行自己的业务,而就在他获取锁成功的那一刻,如果GC结束了,阻塞结束,我们的线程恢复运行,此时它就会去执行释放锁的动作了,因为判断已经执行过了,它认为锁还是自己的,但现在锁已经是线程2的了。此时直接执行释放锁,于是就把线程2的锁给删掉了,有一次发生了误删。

image-20240528182424501

此时又来个线程3,获取锁成功,然后执行自己业务,由此可见,这种并发的问题有一次发生了。

image-20240528182658339

所以这次产生的原因是什么?我们做了判断,但是由于判断锁标识和释放锁是两个动作,这两个动作之间产生了阻塞,最后出现了问题。

因此要想避免这个问题的发生,我们必须确保判断锁的动作和释放锁的动作这两个得成一个原子性的操作,也就是说一起执行,不能出现间隔。

那我们怎么保证两个动作的原子性呢?这个问题下节分析。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值