redis面试(十九)读写锁ReadLock

news2025/1/12 17:22:40

读写锁ReadLock

简单来说就是互斥锁和非互斥锁。多个客户端可以同事加的锁叫读锁,只能有一个客户端加的锁叫写锁。这个理论应该是从数据库中来的,放在这里也是同样的解释。

  • 多个客户端同时加读锁,是不会互斥的,多个客户端可以同时加这个读锁,读锁和读锁是不互斥的
  • 如果有人加了读锁,此时就不能加写锁,任何人都不能加写锁了,读锁和写锁是互斥的
  • 如果有人加了写锁,此时任何人都不能加写锁和读锁了,写锁和写锁也是互斥的

实现

RedissonReadLock是RedissonLock的子类
关注要几块东西,第一个是加读锁的lua脚本的逻辑;第二个是读锁的释放的lua脚本的逻辑;第三个是读锁的wathdog刷新锁key的生存时间的逻辑

RReadWriteLock rwLock = redisson.getReadWriteLock("anyLock");
rwLock.readLock().lock();
rwLock.readLock().unlock();
rwLock.writeLock().lock();
rwLock.writeLock().unlock();

加锁代码

加锁的方法入口都是在RedissonLock类里面,只是在真正加锁的地方用子类来处理。
在这里插入图片描述

点进来就可以看到ReadLcok的lua脚本逻辑,下面就来分析一下
在这里插入图片描述
假设
客户端A(UUID_01:threadId_01)来加读锁
这几个参数拼接之后是下面的形式
KEYS[1] = anyLock
KEYS[2] = {anyLock}:UUID_01:threadId_01:rwlock_timeout

ARGV[1] = 30000毫秒
ARGV[2] = UUID_01:threadId_01
ARGV[3] = UUID_01:threadId_01:write

前两行的的意思就是要从一个名为anyLock的hash结构中,获取一个key为mode的对应的value值
这是第一个线程第一次进来,肯定是空的,条件成立。
local mode = redis.call(‘hget’, KEYS[1], ‘mode’);
if (mode == false) then

新建一个名为anyLock的hash结构,里面有一个键值对mode:read
redis.call(‘hset’, KEYS[1], ‘mode’, ‘read’);

anyLock的hash结构再来个键值对key=UUID_01:threadId_01 value=1
‘hset’, KEYS[1], ARGV[2], 1

set一个键值对,这两个…的意思是拼接字符串KEYS[2] 原本等于{anyLock}:UUID_01:threadId_01:rwlock_timeout
那KEYS[2] … ‘:1’ = {anyLock}:UUID_01:threadId_01:rwlock_timeout:1
所以这里的键值对就是 key={anyLock}:UUID_01:threadId_01:rwlock_timeout:1
value=1
‘set’, KEYS[2] … ‘:1’, 1

是给上面一个hash数据anyLock,一个普通数据{anyLock}:UUID_01:threadId_01:rwlock_timeout:1
设置过期时间 30000毫秒也就是30s
pexpire

现在加完锁返回为空

看门狗

scheduleExpirationRenewal(),这个方法是通用的RedissonLock里面的实现逻辑,但是其中的延时方法renewExpirationAsync() , RedissonReadLock有个自己的实现

在这里插入图片描述

看门狗

lua脚本逻辑
之前我们也分析过普通锁的lua脚本,逻辑是一样的。
简单来说就是只要锁还存在,就不断的延长锁的过期时间避免持有锁的过程中失效。
在这里插入图片描述

假如说刚才已经成功加了读锁,我们来看一下这里的参数
KEYS[1] = anyLock
KEYS[2] = {anyLock}

ARGV[1] = 30000毫秒
ARGV[2] = UUID_01:threadId_01

hget anyLock UUID_01:threadId_01,获取一下当前这个线程是否对这个锁加了一个读锁,这里返回的应该是1,此时可以判定是当前这个线程加的读锁
pexpire anyLock 30000,刷新一下anyLock锁key的生存时间为30000毫秒

hlen anyLock = 2 > 1,就是说,如果你的读锁,anyLock hash内部的key-value对超过了1个,这里肯定是成立的,拿到anyLock所有的key
开始进入循环
这里说是,拿到key对应得值,如果是数字的话,进入下面的循环中,如果不是的话不管他
counter = tonumber(redis.call(‘hget’, KEYS[1], key));
if type(counter) == ‘number’ then
此时counter = 1
for i = counter, 1, -1 do
所以
for i = 1, 1, -1 do

加锁的时候我们知道,anyLock里面有个键值对吗,这里的值也是可重入的,同一个线程每重入一次锁,这里的value就+1,
key=UUID_01:threadId_01 value=1
所以延长锁有效期的时候就要根据这个重入的次数来循环延长。

刚才名为anyLock这个hash结构已经延长过了,现在要延长的就是
key={anyLock}:UUID_01:threadId_01:rwlock_timeout
value=1
这个普通类型的键值对,有一次重入,这个时间就要多延长30s。

pexpire’, KEYS[2] … ‘:’ … key … ‘:rwlock_timeout:’ … i, ARGV[1]

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

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

相关文章

【Excel】Excel小技巧(实时更新中)- 0.0.1

文章目录 单元格操作多列数据"".join()为一个 END 单元格操作 多列数据"".join()为一个 END

Python保留字符

Python中的保留字。 这些保留字不能用作常数或变数,或任何其他标识符名称。 所有 Python 的关键字只包含小写字母。

Java 中边读数据库边写到文件,可以处理大型数据文件而不会消耗太多内存。

从数据库查询结果集中提取单行数据,并按列格式化为字符串形式。主要功能如下: 遍历结果集的每一列。 根据不同的数据类型转换列值为字符串。 使用StringBuilder拼接各列值,列间以colSeparator分隔。 替换字符串中的换行符\n和回车符\r为空字符…

C语言—指针(2)

目录 一、数组名的理解 二、使用指针访问数组 三、一维数组传参的本质 四、冒泡排序 五、二级指针 六、指针数组 七、字符指针变量 八、数组指针变量 (8.1)什么是数组指针变量 (8.2)数组指针变量的初始化 九、二维数组传…

Linux入门——08 进程间通讯——管道

1.进程间通讯 1.1什么是通讯 进程具有独立性(每个进程都有自己的PCB,独立地址空间,页表)但是要进行进程的通信,通信的成本一定不低,打破了独立性 进程间通信目的 数据传输:一个进程需要将它的数据发送给…

探索风扇产品模型的3D可视化魅力

在这个科技日新月异的时代,每一个细微的创新都能为我们的生活带来前所未有的便捷与享受。今天,就让我们一起踏入一场视觉与科技的盛宴,探索风扇产品模型如何通过3D可视化技术,重新定义家居生活的舒适与美学。 想象一下&#xff0c…

Redis—缓存机制

Redis 缓存机制 1. 缓存三兄弟1.1 缓存击穿1.2 缓存穿透1.3 缓存雪崩 2. 布隆过滤器3. 缓存和数据库数据一致性3.1 缓存更新策略3.2 缓存不一致处理 4. 热点 key4.1 热点 key 处理4.2 热点 key 重建 5. 缓存预热 Redis,一个轻量级的开源内存数据结构存储系统&#x…

Java:循环练习

目录 1. 回文判断 2. 减法求商余 3. 求平方根 4.求质数 5. 猜数字 1. 回文判断 输入一个数字,判断是否为回文,回文就是正着读和反着读都一样,如121是回文,123则不是。 import java.util.Scanner;public class DemoNew {publ…

白卡无法注册TDSCDMA问题分析

1、问题描述 MTK平台 实验室白卡测试TDSCDMA,默认无法注册。使用移动卡测试,无此问题。 2、问题分析 查看Radio log,Radio中反复下发EFUN去开关飞行模式。 39191: 08-14 22:45:57.159210 1469 1512 D RmcWp : [0] ECSRA info E…

CART决策树-基尼指数(全网最详解)

文章目录 一、基尼指数的定义二、基尼指数在CART决策树中的应用三、基尼指数与CART决策树的构建1.计算每个子集的基尼系数:2.计算基尼指数3.选择最优特征4.其余基尼指数5.构建决策树 四、总结 CART决策树基尼指数是CART(Classification And Regression T…

稳石机器人 | 工业级AMR S1200L,专为多样化需求设计,柔性拓展更易用

近日,稳石机器人重磅推出基于新品控制器ROC1000的全新移动机器人AMR S1200L,专为满足生产制造和仓储物流的多样化需求而设计,无需改造现场,最快可在1周内完成部署。 重载型AMR-S1200L设计注重实用性和灵活性,可在室内…

Excel 中找出每列第一个和最后一个非空格对应的行--Excel难题#87

Excel表格的第2-6列有空格。 ABCDEF1StartDateQID1QID2QID3QID4QID5210/03/2024 10:561yes32310/03/2024 03:102no423409/03/2024 19:253yes22509/03/2024 11:404no1yes609/03/2024 03:555yes5no708/03/2024 20:106808/03/2024 12:257no908/03/2024 04:408yes1007/03/2024 20:…

Linux云计算 |【第二阶段】SECURITY-DAY4

主要内容: Kali系统、扫描与抓包、Nginx安全加固、Linux基本防护 补充:使用Curl命令查看网页头部信息和页面内容 不加选项,默认查看网页的内容; [ -I ] 选项:访问服务器页面时,显示HTTP的头部信息&#xf…

用阿里云“无影”搭建《黑神话:悟空》电脑环境

目录 《黑神话:悟空》 阿里云无影试用版概述 阿里云无影云电脑试用版情况 具体详细过程(搭建环境) 《黑神话:悟空》 《黑神话:悟空》作为一款高品质的国产游戏,对硬件配置有一定的要求。根据公开发布的…

【鸿蒙学习】HarmonyOS应用开发者高级认证 - 应用性能优化一(界面层面)

学完时间:2024年8月22日 学完排名:第1801名 一、介绍 在开发HarmonyOS应用时,优化应用性能是至关重要的。通过/ArkTS高性能编程、减少丢帧卡顿、提升应用启动和响应速度 可以有效提升用户体验。本文将介绍一些优化HarmonyOS应用性能的方法。 一、Ark…

Go开发桌面客户端软件小试:网站Sitemap生成

在前一篇【手把手教你用Go开发客户端软件(使用Go HTML)】中,我们详细介绍了如何通过Go语言开发一个简单的桌面客户端软件。本次,我们将继续这个系列,使用Go语言结合Sciter的Go绑定库——go-sciter,实战开发…

14.C基础_结构体

定义与使用 1、定义 定义结构体: 定义结构体时,需要注意最后的分号必须加上。 定义结构体时,成员只去声明类型,不进行赋值。赋值在定义结构体变量时进行。 struct 结构体名{结构体成员列表 }; //注意这里的分…

Qt入门学什么?

Qt是一个跨平台的C图形用户界面应用程序框架,它为应用程序开发者提供建立图形界面所需的所有功能。Qt框架以其面向对象、易于扩展的特性而受到广泛欢迎,并且支持多种平台,包括桌面、嵌入式和移动平台 。 对于Qt的入门学习,可以通过…

uniapp+vue3的defineProps传递

//index.vue <view class"topic"><!-- 磨砂背景 --><view class"content"><matte v-for"(item,index) in 8" :key"index"></matte><matte isMore"false"></matte></view>&…

0成本学习Liunx系统【只需要一台笔记本电脑,无需购买云服务器】

【准备工作&#xff0c;需要软件】&#xff1a; 1&#xff1a;MobaXterm 【服务器连接工具&#xff08;免费开源&#xff09;】 2&#xff1a;CentOS-7-x86_64-DVD-2009.iso 【CentOS-7 镜像】 3&#xff1a;VirtualBox-7.0.20-163906-Win.exe 【虚拟机壳子】 4&…