首页 > 数据库 >redis加锁逻辑分析

redis加锁逻辑分析

时间:2023-12-12 14:47:59浏览次数:30  
标签:逻辑 加锁 false redis subscribeFuture System subscribe time TimeUnit

 

public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
//省略部分代码
        time -= System.currentTimeMillis() - current;
        if (time <= 0) {
            acquireFailed(waitTime, unit, threadId);
            return false;
        }
        current = System.currentTimeMillis();
       // 订阅监听redis消息,并且创建RedissonLockEntry
        RFuture<RedissonLockEntry> subscribeFuture = subscribe(threadId);
      // 阻塞等待subscribe的future的结果对象,如果subscribe方法调用超过了time,说明已经超过了客户端设置的最大wait time,则直接返回false,取消订阅,不再继续申请锁了。
        if (!subscribeFuture.await(time, TimeUnit.MILLISECONDS)) {
            if (!subscribeFuture.cancel(false)) { //取消订阅
                subscribeFuture.onComplete((res, e) -> {
                    if (e == null) {
                        unsubscribe(subscribeFuture, threadId);
                    }
                });
            }
            acquireFailed(waitTime, unit, threadId); //表示抢占锁失败
            return false; //返回false
        }
        try {
            //判断是否超时,如果等待超时,返回获的锁失败
            time -= System.currentTimeMillis() - current;
            if (time <= 0) {
                acquireFailed(waitTime, unit, threadId);
                return false;
            }
            //通过while循环再次尝试竞争锁
            while (true) { 
                long currentTime = System.currentTimeMillis();
                ttl = tryAcquire(waitTime, leaseTime, unit, threadId); //竞争锁,返回锁超时时间
                // lock acquired
                if (ttl == null) { //如果超时时间为null,说明获得锁成功
                    return true;
                }
                //判断是否超时,如果超时,表示获取锁失败
                time -= System.currentTimeMillis() - currentTime;
                if (time <= 0) {
                    acquireFailed(waitTime, unit, threadId);
                    return false;
                }

                // 通过信号量(共享锁)阻塞,等待解锁消息.  (减少申请锁调用的频率)
				// 如果剩余时间(ttl)小于wait time ,就在 ttl 时间内,从Entry的信号量获取一个许可(除非被中断或者一直没有可用的许可)。
				// 否则就在wait time 时间范围内等待可以通过信号量
                currentTime = System.currentTimeMillis();
                if (ttl >= 0 && ttl < time) {
                    subscribeFuture.getNow().getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);
                } else {
                    subscribeFuture.getNow().getLatch().tryAcquire(time, TimeUnit.MILLISECONDS);
                }
                // 更新等待时间(最大等待时间-已经消耗的阻塞时间)
                time -= System.currentTimeMillis() - currentTime;
                if (time <= 0) { //获取锁失败
                    acquireFailed(waitTime, unit, threadId);
                    return false;
                }
            }
        } finally {
            unsubscribe(subscribeFuture, threadId); //取消订阅
        }
//        return get(tryLockAsync(waitTime, leaseTime, unit));
    }

  

标签:逻辑,加锁,false,redis,subscribeFuture,System,subscribe,time,TimeUnit
From: https://www.cnblogs.com/HubuSugar/p/17896753.html

相关文章

  • vue 逻辑分页
    <template><div><divclass="paging"><!--数据显示区域--><divclass="data"><!--表格存放数组中的数据,并对数据进行截取,以控制每一页显示的数据量--><!--slice(start,end)不包括end--><el-ta......
  • Redis的IO多路复用原理 - 生活案例解释
    仓库管理员就像一个服务器,负责接收和处理来自多个客户端的请求。快递员就像一个线程,负责处理一个客户端的请求。仓库管理员会根据客户端的送达地点将快递标记好,然后依次放在一个地方。快递员会依次去取快递,一次拿一个,送好了就回来拿下一个快递。这种方式可以实现单个线程(一个快递员......
  • Redis命令整合(五) Zset型
    有序集合。使用分数score来标记每个元素1.添加元素zaddmathScore98jordan86james77kobe添加了三个元素,分数在前 2.假如添加的元素已经存在的话,则会替换原来的分数。zaddmathScore79kobe则将kobe的分数改为79 3.取某一个元素的分数zscoremathScor......
  • Redis命令整合(四) Set型
    集合类型。元素各不相同没有顺序1.添加元素sadd[keyName][member1][member2]...eg:saddlettersabc2.删除元素srem[keyName][member1][member2]...egsremlettersab3.列出所有元素smembers[keyName]eg:smemberletters4.判断是否存在sismem......
  • 判断推理-逻辑判断(论证类-一般质疑)
    一般质疑题型介绍归因类之外的质疑题目,均称为一般质疑,即非谈论因果关系。题目形式一般由论据、结论两部分组成,隐含有论证过程,其中论据应正确、充分,论证过程应有效、严谨,结论应合理。题型分类一般质疑可分为无论据有结论、有论据有结论、严谨逻辑关系三类。提问方......
  • Redis内存淘汰策略
    Redis内存过期策略定时过期设置有效时间的key一旦过期,立马从内存中删除。好处就是内存及时释放,坏处就是不停扫描key,cpu消耗严重惰性过期设置有效时间的key过期,不立马删除key,而是等下一次查询到该key时执行删除动作。好处就是cpu消耗降低,坏处就是消耗内存定期过期每过一段时......
  • Redis缓存问题分析与解决方案
    在分布式系统中,Redis作为一种高效的缓存解决方案,但在面对大规模并发、高负载情境下,可能出现雪崩、击穿和穿透等问题,需要我们采取相应的解决方案。1.Redis雪崩问题描述:Redis雪崩是指缓存中大量的键在同一时刻过期,导致大量请求直接落到数据库上,引发数据库压力骤增。解决方案:随机设......
  • Redis 3 种特殊数据类型详解、Redis内存碎片
    CacheAsidePattern(旁路缓存模式)CacheAsidePattern是我们平时使用比较多的一个缓存读写模式,比较适合读请求比较多的场景。CacheAsidePattern中服务端需要同时维系db和cache,并且是以db的结果为准。下面我们来看一下这个策略模式下的缓存读写步骤。写:先更新db然......
  • PHP里redis的大坑:加号被转为空格
    最近在PHP中使用js把图像的base64存入redis,取出来的时候发现无法正常显示图像。试了无数次,javascript看来看去也没有问题,最终发现是redis的问题:加号全部被自动转为空格了。(尚未仔细检查是否为PHP里的 $redis=newRedis();  这个的问题,还是说这个是redis的原生问题,以后有时......
  • Redis 也支持全文搜索 了?这也太强了
    在2021年我就了解到RediSearch这个项目,并已经把它用于我的开源项目newbee-mall-pro中。就我的使用体验来说,简单场景下,用来平替Elasticsearch的使用场景已经足够。像是Elasticsearch中常用中文分词插件可以用RediSearch替代,但是拼音转中文插件在RediSearch中还没有......