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

11 redis中分布式锁的实现

  1. 单机锁代码
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;public class AloneLock implements Lock {AtomicReference<Thread> owner = new AtomicReference<>();//队列--存放哪些没有抢到锁的线程LinkedBlockingQueue<Thread> waiters = new LinkedBlockingQueue<>();//实现加锁@Overridepublic void lock() {while (!owner.compareAndSet(null,Thread.currentThread())){waiters.add(Thread.currentThread());LockSupport.park();//让当前线程阻塞waiters.remove(Thread.currentThread());//解锁了,就需要把线程从等待列表中删除}}//实现解锁@Overridepublic void unlock() {if(owner.compareAndSet(Thread.currentThread(),null)){for (Object  object:waiters.toArray()){Thread  next= (Thread) object;LockSupport.unpark(next);}}}@Overridepublic void lockInterruptibly() throws InterruptedException {}@Overridepublic boolean tryLock() {return false;}@Overridepublic boolean tryLock(long time, TimeUnit unit) throws InterruptedException {return false;}@Overridepublic Condition newCondition() {return null;}
}
  1. redis分布式锁,之前的博客中也有其他的版本的,只是不支持本地重入方案。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.params.SetParams;import java.util.Arrays;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;/*** 分布式锁的实现*/
@Component
public class RedisDistLock implements Lock {private final static int LOCK_TIME = 5*1000;private final static String RS_DISTLOCK_NS = "tdln:";/*if redis.call('get',KEYS[1])==ARGV[1] thenreturn redis.call('del', KEYS[1])else return 0 end*///释放锁private final static String RELEASE_LOCK_LUA ="if redis.call('get',KEYS[1])==ARGV[1] then\n" +"        return redis.call('del', KEYS[1])\n" +"    else return 0 end";/*保存每个线程的独有的ID值*/private ThreadLocal<String> lockerId = new ThreadLocal<>();/*解决锁的重入*/private Thread ownerThread;private String lockName = "lock";@Autowiredprivate JedisPool jedisPool;public String getLockName() {return lockName;}public void setLockName(String lockName) {this.lockName = lockName;}public Thread getOwnerThread() {return ownerThread;}public void setOwnerThread(Thread ownerThread) {this.ownerThread = ownerThread;}@Overridepublic void lock() {while(!tryLock()){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}}@Overridepublic void lockInterruptibly() throws InterruptedException {throw new UnsupportedOperationException("不支持可中断获取锁!");}@Overridepublic boolean tryLock() {Thread t = Thread.currentThread();if(ownerThread==t){/*说明本线程持有锁*/return true;}else if(ownerThread!=null){/*本进程里有其他线程持有分布式锁*/return false;}Jedis jedis = null;try {String id = UUID.randomUUID().toString();SetParams params = new SetParams();params.px(LOCK_TIME);params.nx();synchronized (this){/*线程们,本地抢锁,防止本地线程的不断重入*/if((ownerThread==null)&&"OK".equals(jedis.set(RS_DISTLOCK_NS+lockName,id,params))){lockerId.set(id);setOwnerThread(t);return true;}else{return false;}}} catch (Exception e) {throw new RuntimeException("分布式锁尝试加锁失败!");} finally {jedis.close();}}@Overridepublic boolean tryLock(long time, TimeUnit unit) throws InterruptedException {throw new UnsupportedOperationException("不支持等待尝试获取锁!");}@Overridepublic void unlock() {if(ownerThread!=Thread.currentThread()) {throw new RuntimeException("试图释放无所有权的锁!");}Jedis jedis = null;try {jedis = jedisPool.getResource();Long result = (Long)jedis.eval(RELEASE_LOCK_LUA,Arrays.asList(RS_DISTLOCK_NS+lockName),Arrays.asList(lockerId.get()));if(result.longValue()!=0L){System.out.println("Redis上的锁已释放!");}else{System.out.println("Redis上的锁释放失败!");}} catch (Exception e) {throw new RuntimeException("释放锁失败!",e);} finally {if(jedis!=null) jedis.close();lockerId.remove();setOwnerThread(null);System.out.println("本地锁所有权已释放!");}}@Overridepublic Condition newCondition() {throw new UnsupportedOperationException("不支持等待通知操作!");}}

问题:分布式锁的过期时间是不太好判断的,如何解决?
看门狗方案,实现自动续期,就是一个守护线程去判断过期时间。

实现方案:Redission插件

相关文章:

11 redis中分布式锁的实现

单机锁代码 import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.con…...

循环链表3

插入函数——插入数据&#xff0c;在链表plsit的pos位置插入val数据元素 位置pos&#xff08;在无特别说明的情况下&#xff09;是从0开始计数的 要改变链表结构&#xff0c;就要依赖前驱&#xff0c;每个前驱的next存储着下一个数据结点的地址&#xff0c;也就是依靠前驱的ne…...

如何修改百科内容?百度百科内容怎么修改?

百科词条创建上去是相当不易的&#xff0c;同时修改也是如此&#xff0c;一般情况下&#xff0c;百科词条是不需要修改的&#xff0c;但是很多时候企业或是人物在近期收获了更多成就或是有更多的变动&#xff0c;这个时候就需要补充维护词条了&#xff0c;如何修改百科内容&…...

mysql8.0英文OCP考试第131-140题

Q131.You have upgraded the MySQL binaries from 5.7.28 to 8.0.18 by using an in-place upgrade. Examine the message sequence generated during the first start of MySQL 8.0.18: 。。。[System]。。。/usx/sbin/mysqld (mysqld 8.0.18-commercial) starting as proces…...

MySQL数据库——存储过程-条件处理程序(通过SQLSTATE指定具体的状态码,通过SQLSTATE的代码简写方式 NOT FOUND)

目录 介绍 案例 通过SQLSTATE指定具体的状态码 通过SQLSTATE的代码简写方式 NOT FOUND 介绍 条件处理程序&#xff08;Handler&#xff09;可以用来定义在流程控制结构执行过程中遇到问题时相应的处理步骤。具体语法为&#xff1a; DECLARE handler_action HANDLER FOR c…...

信号的处理时机(内核态,用户态,如何/为什么相互转换,内核空间,cpu寄存器),信号的处理流程详细介绍+抽象图解

目录 信号的处理时机 引入 思考 -- 什么时候才能算合适的时候呢? 用户态转为内核态 引入 内核地址空间 引入 思考 -- 进程为什么能切换成内核态呢? 虚拟地址空间 注意点 原理 (总结一下) 为什么如何进入内核态 引入 介绍 底层原理(int 80) cpu的寄存器 用…...

【JavaEE】Spring的创建和使用(保姆级手把手图解)

一、创建一个Spring项目 1.1 创建一个Maven项目 1.2 添加 Spring 框架支持 在pom.xml中添加 <dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.3.RELEASE&…...

MyBatis:关联查询

MyBatis 前言关联查询附懒加载对象为集合时的关联查询 前言 在 MyBatis&#xff1a;配置文件 文章中&#xff0c;最后介绍了可以使用 select 标签的 resultMap 属性实现关联查询&#xff0c;下面简单示例 关联查询 首先&#xff0c;先创建 association_role 和 association_…...

第十二章 控制值的转换

文章目录 第十二章 控制值的转换介绍处理特殊 XML 字符文字和 SOAP 编码格式的转义形式 示例防止泄漏的另一种方法 第十二章 控制值的转换 类和属性参数 ESCAPE CONTENT XMLTIMEZONE DISPLAYLIST VALUELIST XMLDEFAULTVALUE XMLLISTPARAMETER XMLSTREAMMODE 介绍 支…...

SQL并集、交集、差集使用

一、概述 SQL语句实现数据的并集&#xff08;union&#xff09;、交集&#xff08;intersect&#xff09;、差集&#xff08;except&#xff09;。 二、案例 1、stu表 idname1张三2李四3王二 2、并集 union union 运算&#xff1a;表示取并集&#xff0c;例如&#xff1a…...

【双指针】盛水最多的容器

盛水最多的容器 文章目录 盛水最多的容器题目描述算法原理思路一思路二 代码实现Java代码实现C代码实现 题目描述 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与…...

win11,引导项管理

1&#xff0c;打开cmd,输入msconfig 2,进入引导选项卡 3&#xff0c;删除不需要的引导项...

YoloV8改进策略:WaveletPool解决小目标的混叠问题,提高小目标的检测精度

文章目录 摘要论文:《抗混叠在微小目标检测中的重要性》1、简介2、相关研究2.1、微小物体检测2.2. 抗锯齿过滤器3、方法3.1. Wavelet Pooling3.2 一致顺序的Wavelet Pooling的WaveCNet3.3、Bottom-Heavy Backbone4、实验4.1、预训练数据集4.2、微小目标检测数据集4.3、抗混叠方…...

JavaScript中的假值对象是什么?

JavaScript是一种非常灵活且强大的编程语言&#xff0c;但有时候它的一些特性可能会让人感到困惑。其中一个常见的问题就是假值对象。在本文中&#xff0c;我们将探讨什么是假值对象&#xff0c;并通过代码示例来解释这个概念。 什么是假值对象&#xff1f; 在JavaScript中&am…...

求二叉树的最大密度(可运行)

最大密度&#xff1a;二叉树节点数值的最大值 如果没有输出结果&#xff0c;一定是建树错误&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 我设置输入的是字符型数据&#xff0c;比较的ASCII值。 输入&#xff1a;FBE###CE### 输…...

V100 GPU服务器安装CUDNN教程

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...

RT-Thread Hoist_Motor PID

本节介绍的是一个举升电机&#xff0c;顾名思义&#xff0c;通过转轴控制物体升降&#xff0c;为双通道磁性译码器&#xff0c;利用电调进行操控&#xff0c;具体驱动类似于大学期间最大众的SG180舵机&#xff0c;在一定的频率下&#xff0c;通过调制脉宽进行控制。 设备介绍…...

css 实现文字流光效果

经过调研发现大多滑块验证码中&#xff0c;有一些文字流光效果&#xff0c;因此在这里简单实现一下。 实现主要利用background 渐变背景以及backgorund-clip:text实现。具体代码如下 css部分 .slide {width: 300px;height: 40px;border: 1px solid #ccc;border-radius: 8px;…...

3D格式转换工具

这里记录下自己之前做3D模型格式转换&#xff0c;包括做CAD模型格式转换辅助的一些开源仓库和工具 &#xff08;一&#xff09;转换成gltf工具 gltf作为3D界的jpg标准&#xff0c;如今已经有很多引擎对其进行了支持&#xff0c;这里单独把它列出来 1. obj转glft工具 git仓库…...

seismicunix基础-声波波动方程推导

seismicunix基础-声波波动方程推导 接触波动方程的研究人员都绕不开这个公式&#xff0c;这是在一维状态下波动方程 但是对于这个方程是怎样来的很少有人能说清楚&#xff0c;其中涉及到牛顿第二运动定律&#xff0c;物体的加速度与受到的力有关。 假设一维弦是大量紧密连接的质…...

别再只用Wireshark了!用Java+Jpcap手撸一个实时网络流量监控工具(附IDEA项目源码)

从零构建Java网络流量监控系统&#xff1a;超越Wireshark的轻量级解决方案 在当今分布式系统和微服务架构盛行的时代&#xff0c;对网络流量的实时监控已成为开发者必备的技能。虽然Wireshark等成熟工具提供了全面的功能&#xff0c;但对于需要深度定制或希望将网络监控能力集成…...

体验 Taotoken 官方价折扣与稳定直连带来的高性价比模型调用

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 体验 Taotoken 官方价折扣与稳定直连带来的高性价比模型调用 对于个人开发者和小型团队而言&#xff0c;在项目开发中集成大模型能…...

告别每次输密码!保姆级教程:在MobaXterm里配置SSH密钥实现一键登录Linux服务器

告别每次输密码&#xff01;保姆级教程&#xff1a;在MobaXterm里配置SSH密钥实现一键登录Linux服务器 每次连接Linux服务器都要输入密码&#xff0c;不仅效率低下&#xff0c;还存在安全隐患。作为一款集成了多种实用功能的终端工具&#xff0c;MobaXterm提供了便捷的SSH密钥管…...

开源工具token-usage-ui:可视化监控LLM API Token用量与成本

1. 项目概述&#xff1a;一个为AI开发者量身打造的Token用量监控利器如果你正在开发基于OpenAI、Anthropic、Azure OpenAI等主流大语言模型API的应用&#xff0c;那么“Token用量”这个指标&#xff0c;你一定不会陌生。它直接关联着你的API调用成本、应用性能&#xff0c;甚至…...

多模态AI视觉语言模型优化与强化学习实践

1. 项目背景与核心价值去年在部署某智能客服系统时&#xff0c;我们发现传统视觉语言模型&#xff08;VLM&#xff09;存在一个致命缺陷——当用户上传一张模糊的产品照片并询问"这个配件该怎么安装"时&#xff0c;系统要么给出笼统的安全提示&#xff0c;要么完全偏…...

终极指南:简单三步在浏览器中免费使用微信网页版

终极指南&#xff1a;简单三步在浏览器中免费使用微信网页版 【免费下载链接】wechat-need-web 让微信网页版可用 / Allow the use of WeChat via webpage access 项目地址: https://gitcode.com/gh_mirrors/we/wechat-need-web 你是否遇到过这样的情况&#xff1a;需要…...

3步解锁Warframe音乐创作:智能演奏系统完全指南

3步解锁Warframe音乐创作&#xff1a;智能演奏系统完全指南 【免费下载链接】ShawzinBot Convert a MIDI input to a series of key presses for the Shawzin 项目地址: https://gitcode.com/gh_mirrors/sh/ShawzinBot 你是否曾经在Warframe中看着Shawzin乐器&#xff0…...

AI代码审查实战:基于LLM的自动化代码质量提升方案

1. 项目概述与核心价值最近在GitHub上看到一个挺有意思的项目&#xff0c;叫abczsl520/codex-review。光看名字&#xff0c;可能有点摸不着头脑&#xff0c;codex这个词在技术圈里通常和OpenAI的Codex模型有关&#xff0c;而review又指向了代码审查。所以&#xff0c;这个项目大…...

告别插件!纯前端Vue2 + WebRTC/FFmpeg.js 实现海康摄像头RTSP流低延迟播放(附与WebSDK控件包对比)

无插件化方案&#xff1a;Vue2 WebRTC/FFmpeg.js实现海康RTSP流低延迟播放实战 在传统监控系统开发中&#xff0c;海康威视WebSDK控件包曾是前端接入摄像头的标准方案&#xff0c;但其依赖浏览器插件、脱离DOM控制的特性&#xff0c;正逐渐成为现代化Web应用的瓶颈。本文将分享…...

Hermes Agent 云端部署实战:从零到一在 DigitalOcean 上构建 24/7 智能体服务

1. 项目概述与核心价值如果你正在构建一个基于 Claude Code 或 agent-skills 的智能体&#xff0c;并且希望它能像一台永不关机的服务器一样&#xff0c;7x24小时在线&#xff0c;随时响应你的指令&#xff0c;那么将 Hermes Agent 部署到云端虚拟服务器&#xff08;VPS&#x…...