分布式锁(仅供自己参考)

分布式锁:满足分布式系统或集群式下多进程可见并且互斥的锁(使用外部的锁,因为如果是集群部署,每台服务器都有一个对应的tomcat,则每个tomcat的jvm就不同,锁对象就不同(加锁的机制,每个jvm有一个锁监听器,里面存放着是否含有所有加锁的对象。有一次线程来,首先判断该线程所具有的所要加锁的对象在锁监视器中是否有,有则让它等待,没有的话则将加锁的对象加进来,再有线程来判断,则和上面的流程一样))(自己理解的流程,可能不对,请指错)

redis实现分布式锁:

一些主要代码:

因为在加锁的时候new的不同的对象,使得每一个name都是不同的。

如果是在高并发的情况下,会有一点的影响(具体的影响是问的chatgpt的)     

        在高并发情况下,如果每个线程都频繁创建和销毁大量对象,这会对Java堆内存产生一定的影响,主要体现在以下几个方面:

  1. 内存使用压力增大:

    • 大量的对象实例占用堆内存空间,可能会导致堆内存使用率急剧上升。
    • 如果不及时回收无用对象,会造成内存溢出(OutOfMemoryError)的风险。
  2. 垃圾回收压力增大:

    • 大量短暂对象的频繁创建和销毁,会增加Java虚拟机的垃圾回收压力。
    • 垃圾回收频率提高,可能会导致应用的性能下降。
  3. 线程间资源竞争:

    • 多个线程同时在堆内存中分配和释放对象,可能会产生线程安全问题。
    • 如果对象的创建和销毁不够规范,可能会导致内存泄漏等问题。
  4. 缓存命中率下降:

    • 大量短暂对象的创建可能会污染CPU缓存,降低缓存命中率。
    • 这会增加内存访问的开销,拖慢整体应用的性能。

可以采用单例模式,也就是在将锁对象作为成员变量,而不是局部变量。(代码参考(参考这里1))

package com.hmdp.utils;import org.springframework.data.redis.core.RedisTemplate;import java.time.Duration;//redis实现的锁机制
public class OrderOneLock implements Lock {private RedisTemplate redisTemplate;private String name;private final String PREFIX_KEY = "lock:";public OrderOneLock(RedisTemplate redisTemplate, String name) {this.redisTemplate = redisTemplate;this.name = name;}@Overridepublic boolean tryLock(long timeOut) {long id = Thread.currentThread().getId();Boolean b = redisTemplate.opsForValue().setIfAbsent(PREFIX_KEY + name, id, Duration.ofSeconds(timeOut));return Boolean.TRUE.equals(b);}@Overridepublic void unLock() {redisTemplate.delete(PREFIX_KEY+name);}
}//加锁Long userId = UserHolder.getUser().getId();//获取锁,看是否获取成功OrderOneLock oneLock = new OrderOneLock(redisTemplate,"order:"+userId); //选择userId是因为每个用户只能选择一单,如果没有userid则全部都使用一单boolean b = oneLock.tryLock(120);if (!b){return Result.fail("只能购买一单");}//能执行到这里,说明加锁成功,则之后必须不管怎么都要释放锁,所以选择finallytry {IVoucherOrderService proxy = (IVoucherOrderService) AopContext.currentProxy();return proxy.getResult(voucherId, userId);} finally {oneLock.unLock();}

参考这里(1)

因为此代码较上边的代码,是为了避免在高并发的情况的大量的创建和销毁对象,而造成性能上的影响。但也是这段代码毕竟麻烦,在于是在销毁锁的时候需要传参数,毕竟有舍有得(具体业务具体分析)。

代码:

package com.hmdp.utils;import org.springframework.data.redis.core.RedisTemplate;import java.time.Duration;public class OrderOneLock implements Lock {private RedisTemplate redisTemplate;//private String name;private final String PREFIX_KEY = "lock:";private String workName; //具体的业务名字public OrderOneLock(RedisTemplate redisTemplate, String name) {this.redisTemplate = redisTemplate;this.workName = name;}@Overridepublic boolean tryLock(long timeOut,String name) {long id = Thread.currentThread().getId();Boolean b = redisTemplate.opsForValue().setIfAbsent(PREFIX_KEY + workName+name, id, Duration.ofSeconds(timeOut));return Boolean.TRUE.equals(b);}@Overridepublic void unLock(String name) {redisTemplate.delete(PREFIX_KEY+workName+name);}
}

上述代码还会造成一种情况,请看下图:

        由于线程1的阻塞,导致redis的key的过期。这时候key过期,线程2就可以拿到锁了,如果这时候线程1,业务完成结束,肯定是需要释放锁的,但这个时候释放的是线程2的锁,而不是线程1它本身的锁。线程2的锁释放之后,但是线程2的业务还未完成,线程3也就来了,导致了有两个线程同时运行,于我们加锁(只能由一个线程执行相违背),而且前一个线程会释放后一个线程的锁。

解决方案:

        给每一个线程的锁都弄一个标识,使得每一个线程都只能由它本身释放,或者过期(这里还没有解决会有多个线程同时执行)

        使用uuid和当前线程号给每一个线程一个标识。uuid在同一个jvm可能相同,但是在不同的jvm之间不同(每一个jvm运行在不同的机器或者虚拟机上)。原因:

  1. UUID生成算法: 在Java中,UUID通常使用RFC 4122中定义的算法生成。这个算法利用了时间戳、MAC地址、随机数等多种因素来生成唯一的UUID。

  2. 时间因素: 算法中使用了时间戳作为生成因素之一。不同的JVM,即使在同一时间生成,由于机器时钟的微小差异,也会导致生成的UUID不同。

  3. 空间因素: UUID的算法还会利用MAC地址作为生成因素。不同的JVM运行在不同的服务器/虚拟机上,MAC地址必不同,这也会导致生成的UUID不同。

           在加上同一个jvm上的线程号是不同的,也就构成了唯一一个标识(jvm使得线程号是递增的)

代码:(自己比较与上面代码的差别)

package com.hmdp.utils;import cn.hutool.core.lang.UUID;
import org.springframework.data.redis.core.RedisTemplate;import java.awt.*;
import java.time.Duration;public class OrderOneLock implements Lock {private RedisTemplate redisTemplate;private String name;private final String PREFIX_KEY = "lock:";private final String mark = UUID.randomUUID().toString(true)+"-";public OrderOneLock(RedisTemplate redisTemplate, String name) {this.redisTemplate = redisTemplate;this.name = name;}@Overridepublic boolean tryLock(long timeOut) {long id = Thread.currentThread().getId();Boolean b = redisTemplate.opsForValue().setIfAbsent(PREFIX_KEY +name, mark+id, Duration.ofSeconds(timeOut));return Boolean.TRUE.equals(b);}@Overridepublic void unLock() {long id = Thread.currentThread().getId();String o = (String) redisTemplate.opsForValue().get(PREFIX_KEY + name);String s = mark + id;if(s.equals(o)){redisTemplate.delete(PREFIX_KEY+name);}}
}

新的情况出现:

如上图:在线程1执行业务完成之后,需要释放锁,在已判断了他是属于他的锁,就要执行 redisTemplate.delete(PREFIX_KEY+name);这句时发生了阻塞(jvm的垃圾回收机制,导致所有代码都不能运行)。一直阻塞。阻塞时间超过了key的过期时间。锁释放。等到阻塞结束,这时又会有线程2进来,线程1也是执行 redisTemplate.delete(PREFIX_KEY+name);这句。这时候线程1就会释放线程2的锁。释放之后就会有线程3进来,这时就会有两个线程执行这个业务(发生了并发),不符合我们的要求。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【UML用户指南】-32-对体系结构建模-部署图

目录 1、对嵌入式系统建模 2、对客户/服务器系统建模 3、对全分布式系统建模 部署图展示运行时进行处理的结点和在结点上生存的制品的配置。 部署图用来对系统的静态部署视图建模。 在UML中,可以 1)利用类图和制品图来思考软件的结构, …

【初阶数据结构】1.算法复杂度

文章目录 1.数据结构前言1.1 数据结构1.2 算法1.3 如何学好数据结构和算法 2.算法效率2.1 复杂度的概念2.2 复杂度的重要性 3.时间复杂度3.1 大O的渐进表示法3.2 时间复杂度计算示例3.2.1 示例13.2.2 示例23.2.3 示例33.2.4 示例43.2.5 示例53.2.6 示例63.2.7 示例7 4.空间复杂…

音视频开发—FFmpeg处理流数据的基本概念详解

文章目录 多媒体文件的基本概念相关重要的结构体操作数据流的基本步骤1.解复用(Demuxing)2.获取流(Stream)3. 读取数据包(Packet)4. 释放资源(Free Resources)完整示例 多媒体文件的…

基于SpringBoot构造超简易QQ邮件服务发送(分离-图解-新手)

目录 获取QQ 授权码 SpringBoot构建 依赖 Yaml配置 服务编写 测试 获取QQ 授权码 https://mail.qq.com/ 接着后就会有对应的密钥了 SpringBoot构建 依赖 这里的建议是 2.0系列的Springboot版本用低一点的邮件依赖 <!-- 电子邮件 --> <dependency>&…

字节码编程javassist之生成带有注解的类

写在前面 本文看下如何使用javassist生成带有注解的类。 1&#xff1a;程序 测试类 package com.dahuyou.javassist.huohuo.cc;import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import ja…

神经网络设计过程

1.可根据Iris特征直接判断 2.神经网络方法&#xff0c;采集大量的Iris特征&#xff0c;分类对应标签&#xff0c;构成数据集。 将数据集喂入搭好的神经网络结构&#xff0c;网络通过反向传播优化参数得到模型。 有新的网络送入到模型里&#xff0c;模型会给出识别结果。 3.…

低空经济火爆:无人机培训机构工作开展详解

随着低空经济的迅速崛起&#xff0c;无人机技术在多个领域得到了广泛应用&#xff0c;从航拍摄影、农业植保到物流配送、环境监测等&#xff0c;都显示出了巨大的市场潜力。无人机培训机构作为培养专业无人机驾驶和操作人才的摇篮&#xff0c;在低空经济的发展中扮演着至关重要…

Vue项目openlayers中使用jsts处理wkt和geojson的交集-(geojson来源zpi解析)

Vue项目openlayers中使用jsts处理wkt和geojson的交集-(geojson来源zpi解析) 读取压缩包中的shape看上一篇笔记&#xff1a;Vue项目读取zip中的ShapeFile文件&#xff0c;并解析为GeoJson openlayers使用jsts官方示例&#xff1a;https://openlayers.org/en/latest/examples/j…

已解决 javax.xml.transform.TransformerFactoryConfigurationError 异常的正确解决方法,亲测有效!!!

已解决 javax.xml.transform.TransformerFactoryConfigurationError 异常的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 目录 一、问题分析 二、报错原因 三、解决思路 四、解决方法 五、总结 博主v&#xff1a;XiaoMing_Java 博主v&#x…

昇思25天学习打卡营第16天|Vision Transformer图像分类

昇思25天学习打卡营第16天|Vision Transformer图像分类 前言Vision Transformer图像分类Vision Transformer&#xff08;ViT&#xff09;简介模型结构模型特点 环境准备与数据读取模型解析Transformer基本原理Attention模块 Transformer EncoderViT模型的输入整体构建ViT 模型训…

【自学网络安全】:安全策略与用户认证综合实验

实验拓扑图&#xff1a; 实验任务&#xff1a; 1、DMZ区内的服务器&#xff0c;办公区仅能在办公时间内(9:00-18:00)可以访问&#xff0c;生产区的设备全天可以访问 2、生产区不允许访问互联网&#xff0c;办公区和游客区允许访问互联网 3、办公区设备10.0.2.10不允许访问Dmz区…

代理详解之静态代理、动态代理、SpringAOP实现

1、代理介绍 代理是指一个对象A通过持有另一个对象B&#xff0c;可以具有B同样的行为的模式。为了对外开放协议&#xff0c;B往往实现了一个接口&#xff0c;A也会去实现接口。但是B是“真正”实现类&#xff0c;A则比较“虚”&#xff0c;他借用了B的方法去实现接口的方法。A…

未羽研发测试管理平台

突然有一些觉悟&#xff0c;程序猿不能只会吭哧吭哧的低头做事&#xff0c;应该学会怎么去展示自己&#xff0c;怎么去宣传自己&#xff0c;怎么把自己想做的事表述清楚。 于是&#xff0c;这两天一直在整理自己的作品&#xff0c;也为接下来的找工作多做点准备。接下来…

wordpress外贸建站公司案例英文模板

Indirect Trade WP外贸网站模板 WordPress Indirect Trade外贸网站模板&#xff0c;建外贸独立站用wordpress模板&#xff0c;快速搭建十分便捷。 衣物清洁wordpress独立站模板 洗衣粉、洗衣液、衣物柔顺剂、干洗剂、衣领净、洗衣皂等衣物清洁wordpress独立站模板。 家具wordpr…

Apache部署与配置

概述 介绍 Apache HTTP Server(简称Apache)是Apache的一个开源的网页服务器&#xff0c;它源自NCSAhttpd服务器&#xff0c;并经过多次修改和发展&#xff0c;如今已经成为全球范围内广泛使用的Web服务器软件之一 特点 跨平台&#xff1a;可以运行在几乎所有广泛使用的计算机平…

哪个充电宝口碑比较好?怎么选充电宝?2024年口碑优秀充电宝推荐

在如今快节奏的生活中&#xff0c;充电宝已然成为我们日常生活中的必备品。然而&#xff0c;市场上充电宝品牌众多&#xff0c;质量参差不齐&#xff0c;如何选择一款安全、可靠且口碑优秀的充电宝成为了消费者关注的焦点。安全性能不仅关系到充电宝的使用寿命&#xff0c;更关…

【正点原子i.MX93开发板试用连载体验】项目计划和开箱体验

本文最早发表于电子发烧友&#xff1a;【   】【正点原子i.MX93开发板试用连载体验】基于深度学习的语音本地控制 - 正点原子学习小组 - 电子技术论坛 - 广受欢迎的专业电子论坛! (elecfans.com)https://bbs.elecfans.com/jishu_2438354_1_1.html 有一段时间没有参加电子发…

clickhouse-jdbc-bridge rce

clickhouse-jdbc-bridge 是什么 JDBC bridge for ClickHouse. It acts as a stateless proxy passing queries from ClickHouse to external datasources. With this extension, you can run distributed query on ClickHouse across multiple datasources in real time, whic…

支持向量机 (support vector machine,SVM)

支持向量机 &#xff08;support vector machine&#xff0c;SVM&#xff09; flyfish 支持向量机是一种用于分类和回归的机器学习模型。在分类任务中&#xff0c;SVM试图找到一个最佳的分隔超平面&#xff0c;使得不同类别的数据点在空间中被尽可能宽的间隔分开。 超平面方…

MMGPL: 多模态医学数据分析与图提示学习| 文献速递-基于深度学习的多模态数据分析与生存分析

Title 题目 MMGPL: Multimodal Medical Data Analysis with Graph Prompt Learning MMGPL: 多模态医学数据分析与图提示学习 01 文献速递介绍 神经学障碍&#xff0c;包括自闭症谱系障碍&#xff08;ASD&#xff09;&#xff08;Lord等&#xff0c;2018年&#xff09;和阿…