【Java】@Transactional事务套着ReentrantLock锁,锁竟然失效超卖了

前言

🍊缘由

Java事务套着锁,就像女色缠着我

在这里插入图片描述

🏀事情起因:

大家好,我是JavaDog程序狗

在一个阳光明媚的中午,我的师傅突然找到我,问了我如下一个问题:

Java中已经加了锁,为什么结果却还是超卖了!

先解释下上述的几个关键词

  • 我的师傅:前阿里大牛,目前屈居青岛大厂管理岗…此处省略一万字夸赞
  • 加锁:模拟使用ReentrantLock加锁,多线程下建议使用Redisson分布式锁实现
  • 超卖:是指系统允许多个用户购买或预订超过实际可用数量的资源

各位小伙伴先有个印象,后续本狗会详细讲解关键词


🎯主要目标

实现4大重点
1. 什么是超卖
2. 超卖如何解决
3. 事务套锁失效问题
4. 解决锁失效问题

🎁如何获取源码

本狗将测试的所有代码均已上传,包含多个示例,小伙伴们可亲测

公众号:【JavaDog程序狗】

关注公众号,发送 “lock”,无任何套路即可获得!

在这里插入图片描述

在这里插入图片描述

正文

🍅情景前置

空调租赁充值时长超卖问题

因我师傅遇到的问题代码涉及隐私,我们就模拟一个场景来分析我们的问题

举例🌰

炎炎夏日,狗哥宿舍因忍受不了酷热,租赁了一台空调,大家在清爽空调的吹拂下渐渐迷失自我

随着租赁时长到期,空调暂停工作,需要我们充值空调使用时长

我们宿舍100个赤膊大汉,分分掏出自己手机同时进行空调使用时长充值…并发超卖问题由此而来

在这里插入图片描述

为此设计了一个设备表,用于下方演示调试

CREATE TABLE `device` (
  `id` bigint(20) NOT NULL COMMENT '主键',
  `use_times` int(10) DEFAULT '0' COMMENT '使用时长',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

在这里插入图片描述

🥦目标分析

一. 什么是超卖?

系统允许多个用户购买或预订超过实际可用数量的资源

👽人话解释

某件商品库存数量1件,结果卖给2个人;更形象的就是双胞胎,一个爱情结晶却喜提两个宝贝

结合上述情景前置,就是宿舍这100个人同时并发操作,按照正常逻辑每个人充值都会在基数+1小时,则总使用时长应为100。

但因为多线程并发问题,可能会导致A和B同时处理逻辑时,获取基数都是同一个,+1后同时更新入库,这样最终的总使用时长就会小于100,出现超卖问题。

出现超卖的代码
@GetMapping("/A")
@Operation(summary = "方式A-更新设备-普通方法(会出现超卖)")
public void payA(@RequestParam Long deviceId) throws InterruptedException {
   
    for(int i=0; i<100; i++){
   
        // 暂停20毫秒,模拟不同时间,不同人请求并发
        Thread.sleep(20);
        // 模拟是个100线程
        new Thread(() -> {
   
            // 更新设备-普通方法
            deviceService.updateDeviceNormal(deviceId);
        }).start();
    }
}
@Override
public void updateDeviceNormal(Long deviceId) {
   
    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JavaDog程序狗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值