redis面试(二十二)读锁释放

news2024/11/15 11:33:40

假设现在已经有各种锁的重入什么的,那如何释放锁?

读锁+读锁

假如说,同一个线程多次加读锁,或者不同的线程加了多个读锁
当前的锁结构长这样
anyLock: {
“mode”: “read”,
“UUID_01:threadId_01”: 2,
“UUID_02:threadId_02”: 1
}
{anyLock}:UUID_01:threadId_01:rwlock_timeout:1 1
{anyLock}:UUID_01:threadId_01:rwlock_timeout:2 1
{anyLock}:UUID_02:threadId_02:rwlock_timeout:1 1

写锁+读锁

或者是同一个线程先加了写锁,后加了读锁,我们看是如果单独释放读锁的
anyLock: {
“mode”: “write”,
“UUID_01:threadId_01:write”: 1,
“UUID_01:threadId_01”: 1
}

{anyLock}:UUID_01:threadId_01:rwlock_timeout:1 1

针对这些情况,如何释放读锁,代码如下
RedissonReadLock.unlockInnerAsync();
在这里插入图片描述
在这里插入图片描述

我们来分析一下,假如说客户端A线程1来释放读锁
先看参数
KEYS[1] = anyLock
KEYS[2] = redisson_rwlock:{anyLock}
KEYS[3] = {anyLock}:UUID_01:threadId_01:rwlock_timeout
KEYS[4] = {anyLock}

ARGV[1] = 0
ARGV[2] = UUID_01:threadId_01

前两行

local mode = redis.call(‘hget’, KEYS[1], ‘mode’);
if (mode == false) then

判断这个key存在不存在,现在已经加了锁,肯定是存在的

再往下

local lockExists = redis.call(‘hexists’, KEYS[1], ARGV[2]);

判断anyLock这个hash表中UUID_01:threadId_01 这个key是否存在,存在的话返回对应的值
现在也肯定是存在的,所以会返回出来一个值

hincrby增量更新,但是后面是-1,所以是原本的值 -1,并且返回更新后的值

local counter = redis.call(‘hincrby’, KEYS[1], ARGV[2], -1);

这两行命令要注意一下,什么情况下值会不等于0?
如果同一个线程多次加了读锁的情况下,那要释放多次,这里只-1,所以肯定是大于0 的,
如果=0的话,就要删除anyLock这个hash表中UUID_01:threadId_01这个key
这里就是读锁+读锁可重入的释放

if (counter == 0) then
redis.call(‘hdel’, KEYS[1], ARGV[2]);

这一行,要删除一个普通的键值对,

redis.call(‘del’, KEYS[3] … ‘:’ … (counter+1));

KEYS[3] = {anyLock}:UUID_01:threadId_01:rwlock_timeout
后面为什么是 (counter+1) 因为刚才不是-1了吗,这里要删除的是原本的值
那拼接后就是{anyLock}:UUID_01:threadId_01:rwlock_timeout:1
这里要删除这个普通键值对,看最上面我们假设的数据结构,确实有这个
如果删除的是重入后的第二次释放
那拼接后就是{anyLock}:UUID_01:threadId_01:rwlock_timeout:2
也是符合重入几次就释放几次的逻辑。

继续往下,这个是判断anyLock这个hash表中的键值对数量,还大于1个吗

if (redis.call(‘hlen’, KEYS[1]) > 1) then

默认是有一个mode的key,每有一个线程加锁,就会新建一个UUID_XX:threadId_XX这种key,那如果有多个读锁的话,现在只释放了一个,key的数量肯定是大于1的

进入if判断里面
定义一个-3的值,后面再说具体什么作用
local maxRemainTime = -3;

取出来anyLock这个hash表中的所有key
local keys = redis.call(‘hkeys’, KEYS[1]);

进入循环for n, key in ipairs(keys) do ,循环取出所有的key

根据hash表中每个key取出来所有的值
counter = tonumber(redis.call(‘hget’, KEYS[1], key));

判断这些值是否是数字,如果是数字的话进入下面的逻辑
if type(counter) == ‘number’ then

如果这个值是多个的话,要从最大开始循环
for i=counter, 1, -1 do

这里是获取过期以毫秒为单位的时间的
local remainTime = redis.call(‘pttl’, KEYS[4] … ‘:’ … key … ‘:rwlock_timeout:’ … i);
maxRemainTime = math.max(remainTime, maxRemainTime);

KEYS[4]={anyLock}
key = UUID_01:threadId_01 /UUID_02:threadId_02 就是所有的key
那最终拼出来的就是
{anyLock}:UUID_01:threadId_01::rwlock_timeout:2
{anyLock}:UUID_02:threadId_02::rwlock_timeout:1
那这里是通过hash表中还存在的读锁,遍历对应的普通键值对锁,来获取他们的最大过期时间

if maxRemainTime > 0 then
redis.call(‘pexpire’, KEYS[1], maxRemainTime);

这个判断是为了延长anyLock这个hash表的过期时间,和对应普通键值锁的过期时间,防止提前过期

if mode == ‘write’ then
return 0

这个是为了应对,先加了写锁,再加读锁的情况。现在读锁已经释放了,写锁不能在这里处理。所以这个逻辑就是判断,如果是写锁的话,要直接返回。

redis.call(‘del’, KEYS[1]);
redis.call(‘publish’, KEYS[2], ARGV[1]);

如果读锁还有其他线程,或者是重入的锁还没释放完,不会走到这里的。都在前面的判断已经拦截了
也就是说,只要能走到这里的都是读锁中所有的线程都释放完毕了,那就要删除这个anyLock的hash锁了。 并且将这个消息进行广播。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2076747.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CRUD的最佳实践,联动前后端,包含微信小程序,API,HTML等(二)

CRUD老生常谈,但是我搜索了一圈,发觉几乎是着重在后端,也就是API部分! 无外乎2个思路 1.归总的接口,比如一个接口,实现不同表的CRUD 2.基于各自的表,使用代码生成器实现CRUD 个人来说是推荐2&am…

css设置input单选radio多选checkbox样式

最近接手一个古老的项目,要修改里边的主题颜色,使用css的var方法一路轻松,最后在input的单选radio和多选checkbox被踩了刹车,也是有几年没做这种原始的项目手生了,最后经过几番折腾后,通过input的伪元素将其…

FPGA开发——使用verilog实现异步FIFO

一、FIFO 介绍 1、FIFO的分类 FIFO ( First In First Out)先进先出存储器。根据接入的时钟信号,可以分为同步 FIFO 和异步 FIFO 。 FIFO 底层是基于双口 RAM ,同步 FIFO 的读写时钟一致,异步 FIFO 读时钟和…

一看就会的Mysql 集群技术

目录 一、Mysql介绍 1.1什么是MySQL 1.2MySQL的优势 1.3MySQL的常用语句 二、MySQL源码安装 三、实验练习 3.1MySQL部署 实验环境 实验步骤 1.创建用户,数据目录,更改权限 2.修改文件 3.初始化,会生成一个密码,将其保…

没有人会窃取你的想法,关键在于执行

没有人会窃取你的想法,关键在于执行 引言 当我第一次读到 Pieter Levels 的创业故事时,我感到无比激动和鼓舞。那种看到未来无限可能的感觉,让我充满了希望与奋斗的力量。他的经历不仅让我明白了创意的价值,更重要的是让我深刻感…

内网穿透的几种方法

内网穿透的几种方法 随着网络技术和应用的不断发展,越来越多的企业和个人需要实现内外网之间的数据交互和服务访问。然而,由于防火墙、NAT(网络地址转换)等安全措施的存在,直接从外部访问内部网络中的服务器或设备变得…

Linux基础软件-dns(一)

作者介绍:简历上没有一个精通的运维工程师。希望大家多多关注作者,下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 Linux进阶部分又分了很多小的部分,我们刚讲完了Linux日常运维。讲的那些东西都算是系统自带的,但是Linux作为一个…

Nvidia驱动莫名其妙不好使了?nvidia-smi报错?如何解决?已解决!!

文章目录 一、报错提示二、解决方案2.1 原因1的解决办法2.2 原因2的解决方案 一、报错提示 Ubuntu20.04出现Failed to initialize NVML: Driver/library version mismatch问题NVIDIA-SMI has failed because it couldn‘t communicate with the NVIDIA driver. 二、解决方案 …

深入探究linux文件IO

一、原子操作和竞争条件 所有系统调用都是以原子操作方式执行的。之所以这么说,是指内核保证了某系统调用中的所有步骤会作为独立操作而一次性加以执行,其间不会为其他进程或线程所中断。 以独占方式创建一个文件 结合 O_CREAT 和 O_EXCL 标志来一次性…

AI学习记录 - 怎么理解 torch 的 torch.nn.BatchNorm2d

画图不易,有用就点个赞 这里创建了一个随机张量,形状为 (4, 3, 4, 4),分别对应 形状为 (batch_size, num_channels, height, width) batch_size:批次 num_channels: 通道(什么是通道看上一章节&#xff0…

串口和RS485通信

一、 定义串口收发数据结构体 /*COM Received Data Structure*/ typedef struct {uint8_t ubr_EndFlag; //Received data end flag uint8_t ubr_buffer[300]; //Received data bufferuint8_t ubr_bufferTemp[300]; //Received data bu…

K-medoids算法原理及Python实践

一、原理 K-medoids算法是一种聚类算法,它的原理与K-Means算法相似,但关键区别在于它使用数据集中的实际点(称为medoids)作为簇的中心点,而不是像K-Means那样使用簇内所有点的平均值。以下是K-medoids算法的主要原理&…

如何在算家云搭建模型Stable-Fast-3D(3D模型生成)

一、模型介绍 Stable-Fast-3D 具有 UV 展开和照明解缠的稳定快速 3D 网格重建,它是一种从单个图像进行快速前馈 3D 网格重建的最先进的开源模型。 二、模型搭建流程 基础环境最低要求说明: 环境名称版本信息1Ubuntu22.04.4 LTSCudaV12.1.105Python3.…

【项目日记】高并发内存池 ---项目介绍及组件定长池的实现

余生还长,你别慌,也别回头,别念旧. --- 余华 --- 1 高并发内存池简介 高并发内存池项目是实现一个高并发的内存池,他的原型是google的一个开源项目tcmalloc,tcmalloc全称Thread-Caching Malloc,即线程缓存…

快速排序与其例题

一、快速排序 1、简单介绍:快速排序(Quick Sort)是一种高效的排序算法,由计算机科学家Tony Hoare在1960年提出。它是基于分治法的排序算法,其基本思想和步骤如下: 基本概念 快速排序的核心思想是将待排序…

一种商业模式既解决引流又解决复购 你想了解一下嘛?

欢迎各位,我是你们的电商策略顾问,吴军。今天,我将向大家介绍一种新颖的商业模式——循环购物模式。这种模式有何独特之处?商家真的在进行慷慨的赠金活动吗?消费者在购物的同时还能获得额外收益?甚至可以将…

Python控制流:条件语句(if, elif, else)①

文章目录 前言1. 基本条件语句1.1 if 语句1.2 else 语句1.3 elif 语句1.4 嵌套条件语句 2. 条件表达式3. 多条件判断4. 比较运算符和逻辑运算符5. 常见错误和最佳实践5.1 常见错误5.2 最佳实践 6. 综合详细的例子:学生成绩管理系统6.1 类和方法Student 类 6.2 主函数…

LD/T698.45 协议解析(新)

通信架构 客户机和服务器在开始通信前,通信信道必须先完成预连接。预连接建立后,默认具有一个最低权限的应用连接,客户机和服务器之间可直接进行数据交换。当客户机需要得到更高权限的服务器服务时,客户机必须发起建立更高权限的…

浦发银行不良堆积,新任领导的无奈

撰稿|芋圆 浦发银行在2023年进行了一波董监高人员大变动,董事长和行长两位掌舵人双双离职,在其任内,浦发银行自2020年起的营收、利润状况和资产质量就一直难有起色。 目前,距新任领导班子上任已差不多过去一年之久。在这一年里&a…

Redis(面试题【速记】)

Redis简介 Redis 是一个开源(BSD 许可)内存数据结构存储用作数据库、缓存、消息代理和流引擎。Redis 提供数据结构,例如 字符串、散列、列表、集合、带范围查询的排序集合、位图、超日志、地理空间索引和流。Redis 内置了复制、Lua 脚本、LRU 驱逐、事务和不同级别的…