实现Redis分布式锁的两种方式


前言

本文主要讲了分布式锁的原子性及实现Redis锁的两种方式。


提示:以下是本篇文章正文内容

一、分布式锁是什么?

分布式锁是控制分布式系统之间同步访问共享资源的一种方式。
(不同机器中不同线程对相同共享资源访问的控制。)

二、分布式锁的原子性

非原子性的分布式锁

代码如下(示例):

	String s = RedisUtils.get(key);
    if (StringUtils.isEmpty(s)) {
         RedisUtils.setex(key, expireTime,expireTime);
         return true;
     }
     return false;

整个设置锁过程分为两步,1、获取锁。2、不存在生成锁并设置过期时间。
加锁是两步操作,这并不能保证分布式锁的原子性。
高并发情况下,线程A和线程B几乎同时进入到加锁这一步,二者都没获取到锁,线程A先设置锁,并返回成功执行业务逻辑;线程B 也加锁成功执行业务逻辑,会造成严重的后果。

三、分布式锁的两种实现思路

1.普通分布式锁

代码如下(示例):

 		long setNx = RedisUtils.setnx(key, Long.toString(expireTime));
        if (setNx ==1L) {
            RedisUtils.expire(key, expireTime);
            return true;
        }
        return false;

Redis单个命令具有原子性,直接用setNx (如果不存在,set进去)命令即可。
其实这也是两步,先设置值,再设置过期时间,但是:
还是刚才那种场景,setNx就不会出现线程A和线程B同时设置key了,必然会有一个线程设置成功,另一个线程设置失败,最终设置过期时间的只会是成功的那个线程。

2.自旋竞争锁

//线程刚进来的时间
long start = System.currentTimeMillis();
for(;;){
	//SET命令返回OK ,则证明获取锁成功
	long setNx = RedisUtils.setnx(key, Long.toString(expireTime));
    if (setNx ==1L) {
         RedisUtils.expire(key, expireTime);
         return true;
     }
    //一直竞争不到锁也不是个事,我们一般设置过期时间内未得到锁,直接退出
    //到结束中间经历的时间
	long end = System.currentTimeMillis() - start;
    if (end >= expireTime * 1000L) {
         return false;
     }
	// 线程等待释放锁,以便下一个for循环竞争锁
    LockSupport.parkNanos(1000* 1000 * 1000);
}

其实就是,当线程开始没有获取到锁的时候,并不立即退出,而是通过无线for循环不断的去竞争锁。

总结

关于上面两种加锁方式使用的业务场景我还有点模糊,欢迎评论区大佬补充。
它两最大的区别就是一个立即退出,另一个等一段时间竞争锁直到竞争不到才退出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值