返回顶部
首页 > 资讯 > 数据库 >redis实现分布式重入锁的方法是什么
  • 604
分享到

redis实现分布式重入锁的方法是什么

2024-04-02 19:04:59 604人浏览 独家记忆
摘要

这篇文章主要为大家分析了Redis实现分布式重入锁的方法是什么的相关知识点,内容详细易懂,操作细节合理,具有一定参考价值。如果感兴趣的话,不妨跟着跟随小编一起来看看,下面跟着小编一起深入学习“redis实现

这篇文章主要为大家分析了Redis实现分布式重入的方法是什么的相关知识点,内容详细易懂,操作细节合理,具有一定参考价值。如果感兴趣的话,不妨跟着跟随小编一起来看看,下面跟着小编一起深入学习“redis实现分布式重入锁的方法是什么”的知识吧。

什么是不可重入锁?

即若当前线程执行某个方法已经获取了该锁,那么在方法中尝试再次获取锁时,就会获取不到而阻塞。

什么是可重入锁?

可重入锁,也叫做递归锁,指的是在同一线程内,外层函数获得锁之后,内层递归函数仍然可以获取到该锁。 就是同一个线程再次进入同样代码时,可以再次拿到该锁。

可重入锁作用?

防止在同一线程中多次获取锁而导致死锁发生。

注:在java的编程中synchronized 和 ReentrantLock都是可重入锁。

基于synchronized的可重入锁

步骤1:双重加锁逻辑

public class SynchronizedDemo {
    //模拟库存100
    int count=100;
    public synchronized void operation(){
        log.info("第一层锁:减库存");
        //模拟减库存
        count--;
        add();
        log.info("下订单结束库存剩余:{}",count);
    }

    private synchronized void add(){
        log.info("第二层锁:插入订单");
        try {
            Thread.sleep(1000*10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

步骤2:加个测试类

public static void main(String[] args) {
    SynchronizedDemo synchronizedDemo=new SynchronizedDemo();
    for (int i = 0; i < 3; i++) {
        int finalI = i;
        new Thread(()->{
            log.info("-------用户{}开始下单--------", finalI);
            synchronizedDemo.operation();
        }).start();
    }
}

步骤3:测试

20:44:04.013 [Thread-2] INFO com.agan.redis.controller.SynchronizedController - -------用户2开始下单--------
20:44:04.013 [Thread-1] INFO com.agan.redis.controller.SynchronizedController - -------用户1开始下单--------
20:44:04.013 [Thread-0] INFO com.agan.redis.controller.SynchronizedController - -------用户0开始下单--------
20:44:04.016 [Thread-2] INFO com.agan.redis.Reentrant.SynchronizedDemo - 第一层锁:减库存
20:44:04.016 [Thread-2] INFO com.agan.redis.Reentrant.SynchronizedDemo - 第二层锁:插入订单
20:44:14.017 [Thread-2] INFO com.agan.redis.Reentrant.SynchronizedDemo - 下订单结束库存剩余:99
20:44:14.017 [Thread-0] INFO com.agan.redis.Reentrant.SynchronizedDemo - 第一层锁:减库存
20:44:14.017 [Thread-0] INFO com.agan.redis.Reentrant.SynchronizedDemo - 第二层锁:插入订单
20:44:24.017 [Thread-0] INFO com.agan.redis.Reentrant.SynchronizedDemo - 下订单结束库存剩余:98
20:44:24.017 [Thread-1] INFO com.agan.redis.Reentrant.SynchronizedDemo - 第一层锁:减库存
20:44:24.017 [Thread-1] INFO com.agan.redis.Reentrant.SynchronizedDemo - 第二层锁:插入订单
20:44:34.017 [Thread-1] INFO com.agan.redis.Reentrant.SynchronizedDemo - 下订单结束库存剩余:97
  • 由于synchronized关键字修饰的是方法,所有加锁为实例对象:synchronizedDemo

  • 运行结果可以看出减库存和插入订单都是每个线程都完整运行两个方法完毕,才能释放锁,其他线程才能拿锁,即是一个线程多次可以拿到同一个锁,可重入。所以synchronized也是可重入锁。

基于ReentrantLock的可重入锁

ReentrantLock,是一个可重入且独占式的锁,是一种递归无阻塞的同步锁。和synchronized关键字相比,它更灵活、更强大,增加了轮询、超时、中断等高级功能。

步骤1:双重加锁逻辑

public class ReentrantLockDemo {

    private Lock lock =  new ReentrantLock();

    public void doSomething(int n){
        try{
            //进入递归第一件事:加锁
            lock.lock();
            log.info("--------递归{}次--------",n);
            if(n<=2){
                try {
                    Thread.sleep(1000*2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                this.doSomething(++n);
            }else{
                return;
            }
        }finally {
            lock.unlock();
        }
    }

}

步骤2:加个测试类

public static void main(String[] args) {
    ReentrantLockDemo reentrantLockDemo=new ReentrantLockDemo();
    for (int i = 0; i < 3; i++) {
        int finalI = i;
        new Thread(()->{
            log.info("-------用户{}开始下单--------", finalI);
            reentrantLockDemo.doSomething(1);
        }).start();
    }
}

步骤3:测试

20:55:23.533 [Thread-1] INFO com.agan.redis.controller.ReentrantController - -------用户1开始下单--------
20:55:23.533 [Thread-2] INFO com.agan.redis.controller.ReentrantController - -------用户2开始下单--------
20:55:23.533 [Thread-0] INFO com.agan.redis.controller.ReentrantController - -------用户0开始下单--------
20:55:23.536 [Thread-1] INFO com.agan.redis.Reentrant.ReentrantLockDemo - --------递归1次--------
20:55:25.537 [Thread-1] INFO com.agan.redis.Reentrant.ReentrantLockDemo - --------递归2次--------
20:55:27.538 [Thread-1] INFO com.agan.redis.Reentrant.ReentrantLockDemo - --------递归3次--------
20:55:27.538 [Thread-2] INFO com.agan.redis.Reentrant.ReentrantLockDemo - --------递归1次--------
20:55:29.538 [Thread-2] INFO com.agan.redis.Reentrant.ReentrantLockDemo - --------递归2次--------
20:55:31.539 [Thread-2] INFO com.agan.redis.Reentrant.ReentrantLockDemo - --------递归3次--------
20:55:31.539 [Thread-0] INFO com.agan.redis.Reentrant.ReentrantLockDemo - --------递归1次--------
20:55:33.539 [Thread-0] INFO com.agan.redis.Reentrant.ReentrantLockDemo - --------递归2次--------
20:55:35.540 [Thread-0] INFO com.agan.redis.Reentrant.ReentrantLockDemo - --------递归3次--------
  • 运行结果可以看出,每个线程都可以多次加锁解锁的,ReentrantLock是可重入的。

redis如何实现分布式重入锁?

setnx虽然可以实现分布式锁,但是不可重入,在一些复杂的业务场景,我们需要分布式重入锁时, 对于redis的重入锁业界还是有很多解决方案的,目前最流行的就是采用Redisson。【相关推荐:Redis视频教程

什么是Redisson?

  • Redisson是Redis官方推荐的Java版的Redis客户端。

  • 基于Java实用工具包中常用接口,为使用者提供了一系列具有分布式特性的常用工具类。

  • 网络通信上是基于NIONetty框架,保证网络通信的高性能。

  • 在分布式锁的功能上,它提供了一系列的分布式锁;如:

    • 可重入锁(Reentrant Lock)

    • 公平锁(Fair Lock)

    • 非公平锁(unFair Lock)

    • 读写锁(ReadWriteLock)

    • 联锁(MultiLock)

    • 红锁(RedLock)

案例实战:体验redis分布式重入锁

步骤1:Redisson配置

Redisson配置的可以查考:redis分布式缓存(三十四)一一 SpringBoot整合Redission - 掘金 (juejin.cn)

https://juejin.cn/post/7057132897819426824

步骤2:Redisson重入锁测试类

public class RedisController {

    @Autowired
    RedissonClient redissonClient;

    @GetMapping(value = "/lock")
    public void get(String key) throws InterruptedException {
        this.getLock(key, 1);
    }

    private void getLock(String key, int n) throws InterruptedException {
        //模拟递归,3次递归后退出
        if (n > 3) {
            return;
        }
        //步骤1:获取一个分布式可重入锁RLock
        //分布式可重入锁RLock :实现了java.util.concurrent.locks.Lock接口,同时还支持自动过期解锁。
        RLock lock = redissonClient.getLock(key);
        //步骤2:尝试拿锁
        // 1. 默认的拿锁
        //lock.tryLock();
        // 2. 支持过期解锁功能,10秒钟以后过期自动解锁, 无需调用unlock方法手动解锁
        //lock.tryLock(10, TimeUnit.SECONDS);
        // 3. 尝试加锁,最多等待3秒,上锁以后10秒后过期自动解锁
        // lock.tryLock(3, 10, TimeUnit.SECONDS);
        boolean bs = lock.tryLock(3, 10, TimeUnit.SECONDS);
        if (bs) {
            try {
                // 业务代码
                log.info("线程{}业务逻辑处理: {},递归{}" ,Thread.currentThread().getName(), key,n);
                //模拟处理业务
                Thread.sleep(1000 * 5);
                //模拟进入递归
                this.getLock(key, ++n);
            } catch (Exception e) {
                log.error(e.getLocalizedMessage());
            } finally {
                //步骤3:解锁
                lock.unlock();
                log.info("线程{}解锁退出",Thread.currentThread().getName());
            }
        } else {
            log.info("线程{}未取得锁",Thread.currentThread().getName());
        }
    }
}

RLock三个加锁动作:


    • lock.tryLock();

    1. 默认的拿锁


    • lock.tryLock(10, TimeUnit.SECONDS);

    1. 支持过期解锁功能,10秒钟以后过期自动解锁


    • lock.tryLock(3, 10, TimeUnit.SECONDS);

    1. 尝试加锁,最多等待3秒,上锁以后10秒后过期自动解锁

区别:

  • lock.lock():阻塞式等待。默认加的锁都是30s

    • 锁的自动续期,如果业务超长,运行期间自动锁上新的30s。不用担心业务时间长而导致锁自动过期被删掉(默认续期)

    • 加锁的业务只要运行完成,就不会给当前锁续期,即使不手动解锁,锁默认会在30s内自动过期,不会产生死锁问题

    • lock()如果我们未指定锁的超时时间,就使用【看门狗默认时间】: lockWatchdogTimeout = 30 * 1000

    • 原理:只要占锁成功,就会启动一个定时任务【重新给锁设置过期时间,新的过期时间就是看门狗的默认时间】,每隔10秒都会自动的再次续期,续成30秒

  • lock.lock(10,TimeUnit.SECONDS) :10秒钟自动解锁,自动解锁时间一定要大于业务执行时间

    • 出现的问题:在锁时间到了以后,不会自动续期

    • 原理:lock(10,TimeUnit.SECONDS)如果我们传递了锁的超时时间,就发送给redis执行脚本,进行占锁,默认超时就是我们制定的时间

最佳实战:

  • lock.lock(10,TimeUnit.SECONDS);  省掉看门狗续期操作,自动解锁时间一定要大于业务执行时间,手动解锁

步骤3:测试

访问3次:Http://127.0.0.1:9090/lock?key=ljw

线程http-nio-9090-exec-1业务逻辑处理: ljw,递归1
线程http-nio-9090-exec-2未取得锁
线程http-nio-9090-exec-1业务逻辑处理: ljw,递归2
线程http-nio-9090-exec-3未取得锁
线程http-nio-9090-exec-1业务逻辑处理: ljw,递归3
线程http-nio-9090-exec-1解锁退出
线程http-nio-9090-exec-1解锁退出
线程http-nio-9090-exec-1解锁退出

通过测试结果:

  • nio-9090-exec-1线程,在getLock方法递归了3次,即证明了lock.tryLock是可重入锁

  • 只有当nio-9090-exec-1线程执行完后,io-9090-exec-2 nio-9090-exec-3 未取得锁 因为lock.tryLock(3, 10, TimeUnit.SECONDS),尝试加锁,最多等待3秒,上锁以后10秒后过期自动解锁 所以等了3秒都等不到,就放弃了

关于“redis实现分布式重入锁的方法是什么”就介绍到这了,更多相关内容可以搜索编程网以前的文章,希望能够帮助大家答疑解惑,请多多支持编程网网站!

您可能感兴趣的文档:

--结束END--

本文标题: redis实现分布式重入锁的方法是什么

本文链接: https://lsjlt.com/news/72153.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • redis实现分布式重入锁的方法是什么
    这篇文章主要为大家分析了redis实现分布式重入锁的方法是什么的相关知识点,内容详细易懂,操作细节合理,具有一定参考价值。如果感兴趣的话,不妨跟着跟随小编一起来看看,下面跟着小编一起深入学习“redis实现...
    99+
    2024-04-02
  • Redis实现分布式锁的方法是什么
    本篇内容介绍了“Redis实现分布式锁的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!在一个分布...
    99+
    2024-04-02
  • Redis分布式锁实现的方法是什么
    本篇内容主要讲解“Redis分布式锁实现的方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Redis分布式锁实现的方法是什么”吧!一、分布式锁是什么分布式锁是 满足分布式系统或集群模式下...
    99+
    2023-07-05
  • 分布式锁redis实现方式是什么
    分布式锁的Redis实现方式有两种:基于SETNX命令和基于RedLock算法。1. 基于SETNX命令:使用Redis的SETNX...
    99+
    2023-09-12
    redis
  • Redis实现分布式锁的五种方法是什么
    本文小编为大家详细介绍“Redis实现分布式锁的五种方法是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“Redis实现分布式锁的五种方法是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起...
    99+
    2024-04-02
  • redis实现分布式锁的方法
    本篇文章展示了redis实现分布式锁的方法具体操作,代码简明扼要容易理解,绝对能让你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。分布式锁其实可以理解为:控制分布式系统有序的去对共享资源进行操作,通过互...
    99+
    2024-04-02
  • redis分布式锁之可重入锁的实现代码
    上篇redis实现的分布式锁,有一个问题,它不可重入。 所谓不可重入锁,即若当前线程执行某个方法已经获取了该锁,那么在方法中尝试再次获取锁时,就会获取不到被阻塞。 同一个人拿一个锁 ...
    99+
    2024-04-02
  • redis中分布式锁的实现方法
    小编给大家分享一下redis中分布式锁的实现方法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!redis分布式锁:1、实现原理利...
    99+
    2024-04-02
  • Redis分布式锁的实现方式
    目录一、分布式锁是什么1、获取锁2、释放锁二、代码实例上面代码存在锁误删问题:三、基于SETNX实现的分布式锁存在下面几个问题1、不可重入2、不可重试3、超时释放4、主从一致性四、Redisson实现分布式锁1、pom2...
    99+
    2023-04-03
    Java Redis分布式锁实现方式 实现Redis分布式锁 Redis分布式锁实现
  • mysql分布式锁实现的方法是什么
    MySQL本身并没有提供分布式锁的实现方法,但可以借助MySQL的特性和其他技术来实现分布式锁。以下是几种常见的实现方法:1. 基于...
    99+
    2023-10-09
    mysql
  • redis实现分布式锁的原理是什么
    这期内容当中小编将会给大家带来有关redis实现分布式锁的原理,以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。分布式锁,是控制分布式系统之间同步访问共享资源的一种方式。在分布式系统中,常...
    99+
    2024-04-02
  • redis分布式锁的实现原理是什么
    这篇文章主要讲解了“redis分布式锁的实现原理是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“redis分布式锁的实现原理是什么”吧!借助于redis...
    99+
    2024-04-02
  • Redis实现分布式锁的方法示例
    之前我们使用的定时任务都是只部署在了单台机器上,为了解决单点的问题,为了保证一个任务,只被一台机器执行,就需要考虑锁的问题,于是就花时间研究了这个问题。到底怎样实现一个分布式锁呢? 锁的本质就是互斥,保证任...
    99+
    2022-06-04
    分布式 示例 方法
  • 使用Redis实现分布式锁的方法
    目录Redis 中的分布式锁如何使用分布式锁的使用场景使用 Redis 来实现分布式锁使用 set key value px milliseconds nx 实现SETNX+Lua 实现使用 Redlock 实现分布式锁...
    99+
    2022-06-16
    Redis分布式锁
  • Redis实现分布式锁方法详细
    目录1. 单机数据一致性2. 分布式数据一致性3. Redis实现分布式锁3.1 方式一3.2 方式二(改进方式一)3.3 方式三(改进方式二)3.4 方式四(改进方式三)3.5 方...
    99+
    2024-04-02
  • redis分布式锁的实现
    一、使用分布式锁要满足的几个条件:1、系统是一个分布式系统(关键是分布式,单机的可以使用ReentrantLock或者synchronized代码块来实现)2、共享资源(各个系统访问同一个资源,资源的载体可...
    99+
    2024-04-02
  • Redis——》实现分布式锁
    推荐链接:     总结——》【Java】     总结——》【Mysql】     总结——》【Redis】     总结——》【Kafka】     总结——》【Spring】     总结—...
    99+
    2023-09-03
    redis 分布式 过期 lua
  • Redis实现分布式锁
    单体锁存在的问题 在单体应用中,如果我们对共享数据不进行加锁操作,多线程操作共享数据时会出现数据一致性问题。 (下述实例是一个简单的下单问题:从redis中获取库存,检查库存是否够,>0才允许下单) 我们的解决办法通常是加锁。如下加单体锁...
    99+
    2023-08-16
    分布式 java jvm
  • Redis实现分布式锁的方法有哪些
    今天小编给大家分享一下Redis实现分布式锁的方法有哪些的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1. 单机数据一致性单...
    99+
    2023-07-02
  • Redis分布式锁的正确实现方式
    Redis分布式锁的正确实现方式?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。可靠性首先,为了确保分布式锁可用,我们至少要确保...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作