乐观锁处理秒杀超卖问题及悲观锁解决一人一单

@Service
@Transactional//事务控制
public class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService {@ResourceSeckillVoucherServiceImpl seckillVoucherService;@ResourceRedisIdWorker redisIdWorker;@ResourceVoucherOrderMapper voucherOrderMapper;@Overridepublic Result seckillVoucher(Long voucherId) {//1.查询优惠券SeckillVoucher voucher = seckillVoucherService.getById(voucherId);//2.判断秒杀是否开始if(voucher.getBeginTime().isAfter(LocalDateTime.now())){return Result.fail("秒杀尚未开始");}//3.判断秒杀是否结束if(voucher.getEndTime().isBefore(LocalDateTime.now())){return Result.fail("秒杀已经结束");}//4.判断是否还有库存if(voucher.getStock()< 1){return Result.fail("库存不足");}//5.扣减库存boolean success=seckillVoucherService.update().setSql("stock = stock-1")//执行手写SQL.eq("voucher_id",voucherId).update();//Where条件if(!success){//扣减失败return Result.fail("库存不足");}//6.创建订单VoucherOrder voucherOrder = new VoucherOrder();//6.1订单IDlong orderId=redisIdWorker.nextId("order");voucherOrder.setId(orderId);//6.2.用户IDLong userId=UserHolder.getUser().getId();voucherOrder.setUserId(userId);//6.3.代金卷IDvoucherOrder.setVoucherId(voucherId);//6.4.写入数据库save(voucherOrder);//7.返回订单号return Result.ok(orderId);}
}

上述代码会出现超卖问题,

 

悲观锁:

悲观锁:认为线程安全问题一定会发生,因此在进行数据库操作之前先获取锁,确保线程串行执行 *Synchronized ,
*Lock都属于悲观锁

乐观锁:

线程安全问题不一定发生,因此不加锁,在更新数据时判断有没有其他线程对数据进行了修改
*若没有修改,则认为是安全的,自己更新数据
*若已经被其他线程修改说明已发生安全问题,此时可以重试或异常

实现乐观锁的关键:判断之前查询得到的数据是否被修改过

1、版本号法,添加version字段 

2.CAS法把库存代替版本号(太聪明了)

  在执行数据库操作时,增加条件stock > 0

 boolean success=seckillVoucherService.update().setSql("stock = stock-1")//set stock = stock-1.eq("voucher_id",voucherId)//where voucher_id=?
//                .eq("stock",voucher.getStock())//where stock=?成功添加乐观锁,但失败率变大.gt("stock",0)//where stack>0,此处有mysql操作自带的锁保证线程安全 .update();

一人一单:

启动类上加暴露代理对象的注解

@MapperScan("com.hmdp.mapper")
@SpringBootApplication
@EnableAspectJAutoProxy(exposeProxy = true)  //暴露代理对象
public class HmDianPingApplication {public static void main(String[] args) {SpringApplication.run(HmDianPingApplication.class, args);}
}

实现一人一单

 @Overridepublic Result seckillVoucher(Long voucherId) {//1.查询优惠券SeckillVoucher voucher = seckillVoucherService.getById(voucherId);//2.判断秒杀是否开始if(voucher.getBeginTime().isAfter(LocalDateTime.now())){return Result.fail("秒杀尚未开始");}//3.判断秒杀是否结束if(voucher.getEndTime().isBefore(LocalDateTime.now())){return Result.fail("秒杀已经结束");}//4.判断是否还有库存if(voucher.getStock()< 1){return Result.fail("库存不足");}Long userId = UserHolder.getUser().getId();//定义同步代码块,userId作为锁对象//使用intern方法可以确保所有相同的 userId 都使用同一个字符串对象作为锁//将锁添加在整个方法上,防止先释放锁,后提交业务//synchronized是JVM的本地锁,若为分布式应用,需要分布式锁synchronized (userId.toString().intern()) {//获取代理对象(事务),使得事务得以生效IVoucherOrderService proxy = (IVoucherOrderService) AopContext.currentProxy();return proxy.createVoucherOrder(voucherId);}}@Transactional//确保本方法中的数据库操作在同一个事务中public Result createVoucherOrder(Long voucherId) {//5.一人一单(需要加锁实现)Long userId = UserHolder.getUser().getId();synchronized (userId.toString().intern()) {//5.1.查询订单int count = query().eq("user_id", userId)//where user_id=?.eq("voucher_id", voucherId).count();//5.2.判断是否已经存在if (count > 0) {return Result.fail("本优惠卷每个用户仅限一单");}//6.扣减库存,添加乐观锁,处理超卖问题boolean success = seckillVoucherService.update().setSql("stock = stock-1")//set stock = stock-1.eq("voucher_id", voucherId)//where voucher_id=?//.eq("stock",voucher.getStock())//where stock=?成功添加乐观锁,但失败率变大.gt("stock", 0)//where stack>0,此处有mysql操作自带的锁保证线程安全.update();if (!success) {//扣减失败return Result.fail("库存不足");}//7.创建订单VoucherOrder voucherOrder = new VoucherOrder();//7.1订单IDlong orderId = redisIdWorker.nextId("order");voucherOrder.setId(orderId);//7.2.用户IDvoucherOrder.setUserId(userId);//7.3.代金卷IDvoucherOrder.setVoucherId(voucherId);//7.4.写入数据库save(voucherOrder);//8.返回订单号return Result.ok(orderId);}

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

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

相关文章

Navicat连接数据库

一、MySQL地卸载&#xff1a; 二、Navicat连接数据库&#xff1a; 安装navicat的安装&#xff1a; 错误解决方法&#xff1a; 实验过程&#xff1a; 在本地sql数据库可以访问&#xff0c;说明数据库开启 用navicat连接&#xff1a;出现问题&#xff1a; 将mysql用户登录的加密…

图论系列(dfs)9.25

一、主题空间 场地由若干主题空间与走廊组成&#xff0c;场地的地图记作由一维字符串型数组 grid&#xff0c;字符串中仅包含 "0"&#xff5e;"5" 这 6 个字符。地图上每一个字符代表面积为 1 的区域&#xff0c;其中 "0" 表示走廊&#xff0…

计算机毕设选题推荐-基于python的电子健康信息分析系统【源码+文档+调试】

精彩专栏推荐订阅&#xff1a;在下方主页&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f496;&#x1f525;作者主页&#xff1a;计算机毕设木哥&#x1f525; &#x1f496; 文章目录 一、电子健康信息…

H7-TOOL脱机烧录增加国产3PEAK混合信号单片机TPS32和富芮坤FR8008,FR8003和FR2012支持

支持单路&#xff0c;1拖4和1拖16脱机烧录 3PEAKS思瑞浦混合信号单片机TPS32M支持 1、在线烧录&#xff0c;脱机烧录均正常。 2、注意事项&#xff1a;推荐使用整片擦除。 在线烧录&#xff1a; 脱机烧录&#xff1a; 接线效果&#xff1a; 富芮坤FR8008x支持&#xff0c;支…

校园自助打印系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;店长管理&#xff0c;打印店管理&#xff0c;打印服务管理&#xff0c;服务类型管理&#xff0c;预约打印管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&…

java基础课程-spring security基础课程

1. spring security介绍&#xff1a; 1.1 spring security定义&#xff1a; 2. Spring Security使用 2.1 用户身份认证&#xff1a; 2.1.1 写在配置文件中&#xff1a; 2.1.2 不用配置文件&#xff1a;&#xff0c;service实现UserDetailService这个类的的loadUserByUserNam…

CNVD漏洞和证书挖掘经验总结

前言 本篇文章主要是分享一下本人挖掘CVND漏洞碰到的一些问题&#xff0c;根据过往成功归档的漏洞和未归档的漏洞总结出的经验&#xff0c;也确实给审核的大佬们添了很多麻烦&#xff08;主要真的没人教一下&#xff0c;闷着头尝试犯了好很多错误&#xff0c;希望各位以后交一个…

JavaScript类型转换和相等性详解

类型转换 10"objects" //10objects,数字10转换为字符串 "7"*"4" //28&#xff0c;两个字符串均转为数字,只要不是加&#xff0c;其他都按两个数字算 var n 1-"x"// NaN&#xff0c;字符串x无法转化为数字 n"objects"//…

微服务--Docker

Docker是一个开源的应用容器引擎&#xff0c;它基于Go语言并遵从Apache2.0协议开源。Docker提供了一种轻量级、可移植和自包含的容器化环境&#xff0c;使开发人员能够在不同的计算机上以一致的方式构建、打包和分发应用程序。 一、Docker的基本概念 容器&#xff08;Contain…

TON生态系统开发指南:从零开始构建你的Web3应用

随着Web3的不断发展&#xff0c;TON&#xff08;The Open Network&#xff09;生态系统逐渐成为备受瞩目的区块链平台。依托其与Telegram的深度整合&#xff0c;TON生态为开发者提供了一个极具潜力的开发环境&#xff0c;特别是在社交、支付和金融这三个核心领域。本文旨在帮助…

企业源代码也需要加密?2024十款源代码加密软件排行榜

在当今数字化时代&#xff0c;源代码作为企业的核心资产&#xff0c;其重要性不言而喻。源代码不仅是企业技术创新的体现&#xff0c;更是商业机密和竞争优势的基石。然而&#xff0c;随着网络攻击和数据泄露事件的频发&#xff0c;源代码的安全性面临着前所未有的挑战。企业源…

零基础转行学网络安全怎么样?能找到什么样的工作?

网络安全对于现代社会来说变得越来越重要&#xff0c;但是很多人对于网络安全的知识却知之甚少。那么&#xff0c;零基础小白可以学网络安全吗&#xff1f;答案是肯定的。 零基础转行学习网络安全是完全可行的&#xff0c;但需要明确的是&#xff0c;网络安全是一个既广泛又深入…

centos7 更新 yum源 为 阿里云 LTS

centos7 更新 yum源 为 阿里云 按照下面的 步骤 1,2&#xff0c;3,4 来一遍 参考文档 CentOS yum源设置为国内aliyun yum源 https://developer.aliyun.com/article/1523301?spm5176.26934562.main.2.16c938e4ys9prQ CentOS 镜像 https://developer.aliyun.com/mirror/cent…

【每天学点AI】五个阶段带你了解人工智能大模型发展史!

20世纪50年代 NLP的早期研究主要基于规则的方法&#xff0c;依赖于语言学专家手工编写的规则和词典。这些规则通常是关于语法、语义和句法结构的人工规则。 例如一个简单的陈述句通常遵循“主语 谓语 宾语”的结构&#xff0c;每一个陈述句都以这种规则做标记。 那时候的NLP…

SpringCloud之服务网关zuul初级篇

SpringCloud之服务网关zuul初级篇 前面的文章我们介绍了&#xff0c;Eureka用于服务的注册于发现&#xff0c;Feign支持服务的调用以及均衡负载&#xff0c;Hystrix处理服务的 熔断防止故障扩散&#xff0c;Spring Cloud Config服务集群配置中心&#xff0c;似乎一个微服务框…

从 Tesla 的 TTPoE 看资源和算法

特斯拉的 ttpoe 出来有一段时间了&#xff0c;不出所料网上一如既往的一堆 pr 文&#xff0c;大多转译自 演讲 ppt 和 Replacing TCP for Low Latency Applications&#xff0c;看了不下 20 篇中文介绍&#xff0c;基本都是上面这篇文章里的内容&#xff0c;车轱辘话颠来倒去。…

大数据毕业设计选题推荐-超市进货推荐系统-Hive-Hadoop-Spark

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

CSS 实现元素根据自身位置进行偏移

代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><style>.item {…

约克VRF中央空调打造Dream home的神器~

开空调真的怕直吹&#xff0c;还怕噪音影响睡眠。我家有小宝宝&#xff0c;更担心温度不均匀会感冒。但约克VRF中央空调真的打破了这些烦恼&#xff01;开了它&#xff0c;家里的舒适感直线上升&#xff0c;温度特别均匀&#xff0c;不会忽冷忽热&#xff0c;小宝宝在家玩得可开…

吴师兄:非科班程序员,创作出Github标星75.3K的宝藏项目,一周爆火……

这是《开发者说》的第18期&#xff0c;今天我们采访的是在Github上传LeetCode动画题解&#xff0c;获得75.3K标星宝藏项目的程序员吴师兄。 吴师兄从985大学毕业&#xff0c;从通信工程外包零基础转码程序员&#xff0c;逐渐进入一些中厂和大厂&#xff0c;工资也从三四千起步…