当前位置: 首页 > news >正文

redis面试(二十三)写锁释放

先加了写锁,后面再次加写锁或者读锁

anyLock: {
“mode”: “write”,
“UUID_01:threadId_01:write”: 2,
“UUID_01:threadId_01”: 1
}

写锁的释放lua脚本在这里
RedissonWriteLock.unlockInnerAsync()
在这里插入图片描述

比如说现在的参数是这
KEYS[1] = anyLock
KEYS[2] = redisson_rwlock:{anyLock}

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

下面来分析一下lua脚本

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

这几行不用多说,先获取anyLock这个hash表中key为mode对应的值,如果不存在的话,锁肯定是已经释放或者过期了

if (mode == ‘write’) then
如果是写锁的话才会继续执行,不是的话直接返回1

local lockExists = redis.call(‘hexists’, KEYS[1], ARGV[3]);
if (lockExists == 0) then

判断anyLock这个hash表中key=UUID_01:threadId_01:write 是否存在,存在的话证明这个线程对应的写锁是存在的,不存在的话直接返回null

local counter = redis.call(‘hincrby’, KEYS[1], ARGV[3], -1);
if (counter > 0) then
redis.call(‘pexpire’, KEYS[1], ARGV[2]);

现在已经确定写锁是存在的,并且需要释放,那这个参数hincrby之前见过好多次了,就是增量更新命令,这里给的是-1,所以是将anyLock这个hash表中key=UUID_01:threadId_01:write,对应的value值-1,并且返回更新后的值。这里就是处理可重入锁的逻辑

如果这个更新后的值大于0的话,证明还有读锁需要释放,这个锁不能过期,那就更新一下过期时间。

redis.call(‘hdel’, KEYS[1], ARGV[3]);
走到这里的话,证明这个写锁没有重入,那就删除anyLock这个hash表中key=UUID_01:threadId_01:write的键值对。

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

这个命令就很有意思了,hlen命令是获取anyLock这个hash表中还有多少键值对,如果是1个的话,那肯定是只剩下mode这个key了,删除这个anyLock,广播一下就结束了

但是如果大于1个的话,就说明还有其他的key
那什么情况下还会有多余的key呢,写锁是互斥的,只能重入,但是可重入的逻辑在上面已经处理过了。那这里的其他key就只能是这个线程后来加的读锁了。
所以这里就是为了处理写锁+读锁的情况

redis.call(‘hset’, KEYS[1], ‘mode’, ‘read’);
如果释放完写锁,还存在其他锁,那这个锁一定是读锁,所以就将mode变成read,此时这个写锁就完全变成读锁了,等待读锁逻辑的处理。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 如何使用Svg矢量图封装引用到vue3项目中
  • JavaEE-servlet
  • 云计算基础之Docker
  • Linux网络编程入门及OSI七层模型
  • 基于Fail2Ban入侵防御软件预防通过ssh暴力破解
  • BEV学习---LSS-1:论文原理及代码串讲
  • 智谱携基座大模型 GLM-4-Plus 亮相 KDD,清言全新升级视频通话功能
  • 面试题集锦:数据库
  • 治愈系风景视频素材下载网站有哪些?令人治愈美景素材库网站分享
  • 使用安信可Ai-WB2-12F开启wifi与手机通信TCP-IP(AT指令)
  • C++系列-泛型编程概念及函数模板
  • Vue3其他Api
  • React中实现antd自定义图标,鼠标悬浮变色
  • RecyclerView网格布局如何动态设置item的显示个数
  • 【虚拟化】使用packer手搓安装linux,windows镜像并导入virsh进行管理(含Kickstart安装与linux内核参数配置)
  • 《Javascript高级程序设计 (第三版)》第五章 引用类型
  • Android Studio:GIT提交项目到远程仓库
  • CSS盒模型深入
  • gitlab-ci配置详解(一)
  • Golang-长连接-状态推送
  • HashMap ConcurrentHashMap
  • JAVA 学习IO流
  • Java面向对象及其三大特征
  • mongodb--安装和初步使用教程
  • Nginx 通过 Lua + Redis 实现动态封禁 IP
  • Python_OOP
  • SegmentFault 社区上线小程序开发频道,助力小程序开发者生态
  • select2 取值 遍历 设置默认值
  • Transformer-XL: Unleashing the Potential of Attention Models
  • UEditor初始化失败(实例已存在,但视图未渲染出来,单页化)
  • 从重复到重用
  • 记一次删除Git记录中的大文件的过程
  • 精益 React 学习指南 (Lean React)- 1.5 React 与 DOM
  • 使用putty远程连接linux
  • 追踪解析 FutureTask 源码
  • 3月7日云栖精选夜读 | RSA 2019安全大会:企业资产管理成行业新风向标,云上安全占绝对优势 ...
  • 如何正确理解,内页权重高于首页?
  • 我们雇佣了一只大猴子...
  • ​RecSys 2022 | 面向人岗匹配的双向选择偏好建模
  • # Redis 入门到精通(九)-- 主从复制(1)
  • # 计算机视觉入门
  • #微信小程序:微信小程序常见的配置传旨
  • #我与Java虚拟机的故事#连载01:人在JVM,身不由己
  • $HTTP_POST_VARS['']和$_POST['']的区别
  • (13):Silverlight 2 数据与通信之WebRequest
  • (不用互三)AI绘画:科技赋能艺术的崭新时代
  • (附源码)计算机毕业设计SSM基于健身房管理系统
  • (面试必看!)锁策略
  • (七)Appdesigner-初步入门及常用组件的使用方法说明
  • (收藏)Git和Repo扫盲——如何取得Android源代码
  • (图文详解)小程序AppID申请以及在Hbuilderx中运行
  • (一)eclipse Dynamic web project 工程目录以及文件路径问题
  • .java 9 找不到符号_java找不到符号
  • .Net core 6.0 升8.0
  • .NET 设计一套高性能的弱事件机制