想法:使用可重入锁实现预锁库存,防止超卖现象,数据库中存入100件商品,测试时每次购买一件,预锁定一件。理想状态是无超卖现象。

@PostMapping("/buyLock")@Transactional(rollbackFor = Exception.class,isolation = SERIALIZABLE)public String buyLock(Integer quantity,Long skuId){lock.lock();try {PmsSkuStock skuStock = skuStockMapper.selectByPrimaryKey(skuId);int left = skuStock.getStock() - skuStock.getLockStock();if (left < quantity){return "库存不足";}int s = skuStockMapper.updateLockStock(skuId,quantity);if (s == 1){return "购买成功";}}catch (Exception e){e.printStackTrace();}finally {lock.unlock();}return "购买失败";}

结果发生了超卖,实际锁定了101件。

解决方法一:去掉@Transactional注解,再试,没有超卖了

@PostMapping("/buyLock")public String buyLock(Integer quantity,Long skuId){lock.lock();try {PmsSkuStock skuStock = skuStockMapper.selectByPrimaryKey(skuId);int left = skuStock.getStock() - skuStock.getLockStock();if (left < quantity){return "库存不足";}int s = skuStockMapper.updateLockStock(skuId,quantity);if (s == 1){return "购买成功";}}catch (Exception e){e.printStackTrace();}finally {lock.unlock();}return "购买失败";}

解决方法二:加上@Transactional注解,将锁提到事务外面,没有超卖

@PostMapping("/buyLock")public String buyLock(Integer quantity,Long skuId){lock.lock();try {return buyLock1(quantity,skuId);}catch (Exception e){e.printStackTrace();}finally {lock.unlock();}return "购买失败";}@Transactional(rollbackFor = Exception.class)public String buyLock1(Integer quantity,Long skuId){PmsSkuStock skuStock = skuStockMapper.selectByPrimaryKey(skuId);int left = skuStock.getStock() - skuStock.getLockStock();if (left < quantity){return "库存不足";}int s = skuStockMapper.updateLockStock(skuId,quantity);if (s == 1){return "购买成功";}return "购买失败";}

解决方法三:spring事务默认使用mysql默认的事务隔离级别,是可重复读,将spring事务级别设置成序列化,没有超卖

@PostMapping("/buyLock")@Transactional(rollbackFor = Exception.class,isolation = SERIALIZABLE)public String buyLock(Integer quantity,Long skuId){lock.lock();try {PmsSkuStock skuStock = skuStockMapper.selectByPrimaryKey(skuId);int left = skuStock.getStock() - skuStock.getLockStock();if (left < quantity){return "库存不足";}int s = skuStockMapper.updateLockStock(skuId,quantity);if (s == 1){return "购买成功";}}catch (Exception e){e.printStackTrace();}finally {lock.unlock();}return "购买失败";}

结论:

发生上述现象的原因是,事物未提交之前,锁已经释放(事物提交是在整个方法执行完),导致另一个事物读取到了这个事物未提交的数据

spring事务和加可重入锁解决库存超卖遇到的问题相关推荐

  1. mysql乐观锁处理超卖_通过乐观锁解决库存超卖的问题

    前言 在通过多线程来解决高并发的问题上,线程安全往往是最先需要考虑的问题,其次才是性能.库存超卖问题是有很多种技术解决方案的,比如悲观锁,分布式锁,乐观锁,队列串行化,Redis原子操作等.本篇通过M ...

  2. 面试官让我设计一个基于分布式锁的库存超卖方案,并发量很高的那种

    今天给大家聊一个有意思的话题:每秒上千订单场景下,如何对分布式锁的并发能力进行优化? 背景引入 首先,我们一起来看看这个问题的背景? 前段时间有个朋友在外面面试,然后有一天找我聊说:有一个国内不错的电 ...

  3. 阿里面试官:高并发大流量秒杀系统如何正确的解决库存超卖问题?(建议收藏)

    大家好,我是冰河~~ 在[精通高并发系列]的<实践出真知:全网最强秒杀系统架构解密!!>一文中,冰河详细的阐述了高并发秒杀系统的架构设计,也简单提到了如何扣减商品的库存. 也许不少小伙伴会 ...

  4. Redis解决库存超卖问题,大厂直通车

    查询商品信息 (调用商品服务) 计算总价(生成订单详情) 商品服务扣库存(调用商品服务) 订单入库( 生成订单) // 原始的MySQL同步流程 // 判断此代金券是否加入抢购 SeckillVouc ...

  5. python threading lock_python threading之死锁和可重入锁

    一.死锁 简单来说,死锁是一个资源被多次调用,而多次调用方都未能释放该资源就会造成死锁,这里结合例子说明下两种常见的死锁情况. 1.迭代死锁 该情况是一个线程"迭代"请求同一个资源 ...

  6. java可重入锁是什么意思_Java中的可重入(Reentrant)锁

    ## 什么是可重入锁? 可重入锁是一种特殊的互斥锁,它可以被同一个线程多次获取,而不会产生死锁. 1. 首先它是互斥锁:任意时刻,只有一个线程锁.即假设A线程已经获取了锁,在A线程释放这个锁之前,B线 ...

  7. 用分布式锁来防止库存超卖,但是是每秒上千订单的高并发场景,如何对分布式锁进行高并发优化来应对这个场景?

    用分布式锁来防止库存超卖,但是是每秒上千订单的高并发场景,如何对分布式锁进行高并发优化来应对这个场景? 转载 codeing_doc 最后发布于2018-11-23 09:44:41 阅读数 1073 ...

  8. 基于 MySQL 排它锁实现分布式可重入锁解决方案

    一.MySQL 排它锁和共享锁 在进行实验前,先来了解下MySQL 的排它锁和共享锁,在 MySQL 中的锁分为表锁和行锁,在行锁中锁又分成了排它锁和共享锁两种类型. 1. 排它锁 排他锁又称为写锁, ...

  9. 年轻人,看看Redisson分布式锁—可重入锁吧!太重要了

    1.引言 作为后端开发,对于所谓的线程安全.高并发等一系列名词肯定都不会陌生,相关的一些概念及技术框架是面试中的宠儿,也是工作中解决一些特定场景下的技术问题的银弹.今天我们就来聊聊这些银弹中的其中一枚 ...

  10. 年轻人,看看 Redisson 分布式锁—可重入锁吧!太重要了

    作者 | 李祥    责编 | 张文 来源 | 企鹅杏仁技术站(ID:xingren-tech) 引言 作为后端开发,对于所谓的线程安全.高并发等一系列名词肯定都不会陌生,相关的一些概念及技术框架是面 ...

最新文章

  1. android 关机充电流程
  2. MySQL中的多表连接
  3. 漫谈分布式事务的那些解决方案
  4. phpcmsv9修改表单直接在列表中显示字段方法
  5. (8)小白又如何?3分钟搞定一个 C# 知识点
  6. python如何退出命令行_如何退出python命令行
  7. JAVA中断线程的方法
  8. Jupyter的安装和基本使用
  9. java中断异常_Java中断异常 InterruptedException 的正确处理方式
  10. struts工作原理(图解)
  11. 计算机达人成长之路(8)连载
  12. MyEclipse安装插件egit并上传项目到码云
  13. 中外大学及大学生活面貌的实录(计算机专业大一学生有感网摘记录) (原创,2013年2月21日不断更新中)...
  14. 按键精灵手机助手之入门篇
  15. 落地干货:三个核心步骤,做好销售管理
  16. matlab从无到有系列(九):Simulink基础仿真详解(全网最全,从入门到放弃)
  17. 1000行代码入门python-小白入门篇,Python到底是什么?
  18. 信签纸有虚线怎么写_写观后感的信签纸格式
  19. NamingContainer取得 GridView的列数(RowIndex)、对应的资料表 这一列的主索引键
  20. 怎么接受对方tp_恋爱关系中怎么和回避型有效沟通

热门文章

  1. 大数据apache-spark问题总结
  2. Science观点:不同细菌物种间极少合作—合理利用细菌间普遍存在的竞争关系来替代抗生素...
  3. 基于SSM+SpringBoot+Thymeleaf+LayUI的高校大学生成绩分析管理系统(附论文)
  4. Tolua使用笔记(上)
  5. 点到线段的距离 计算几何
  6. C4D R26 安装教程
  7. Twaver-HTML5基础学习(8)拓扑元素(Element)_网元(Element)、节点(Node)
  8. 电子书管理神器 calibre 5.0.0中文版
  9. python 多行注释 快捷键
  10. win10修改git账号和密码