Springboot在有锁的情况下如何正确使用事务
1. 概述
老话说的好:想要赚钱,就去看看有钱人有什么需求,因为有钱人钱多,所以赚的多。
言归正传,在Java项目的研发中,“锁”这个词并不陌生,最经典的使用场景是商品的超卖问题。
很多Java小白,通常会认为,给代码加上一把“锁”,就能解决多扣库存问题,却忽略了数据库事务的问题,今天我们就来做一个实验,分析一下商品超卖问题。
2. 场景介绍
有一款商品,库存只剩1件。
购买商品时,做三个动作,一是检查库存,二是扣库存,三是生成订单,三个动作在一个事务中执行。
模拟并发场景,使用10个线程同时执行用户购买商品的操作。
3. 代码实现
3.1 不加锁的代码实现
@Transactional(rollbackFor = Exception.class)
public void buy() { // 查看是商品否有库存
Integer count = getProductCount();
if(count <= 0) {
throw new RuntimeException("库存为 0");
} // 减库存
productRepository.reductCount(); // 生成订单
createOrder();
}
首先我们正常编写业务逻辑,用 @Transactional 注解控制事务。
经并发实验,产生了超卖的现象。
3.2 加锁的代码实现
@Transactional(rollbackFor = Exception.class)
public synchronized void buy() { // 查看是商品否有库存
Integer count = getProductCount();
if(count <= 0) {
throw new RuntimeException("库存为 0");
} // 减库存
productRepository.reductCount(); // 生成订单
createOrder();
}
这次我们使用 synchronized 关键字给方法加了把“锁”,理论上应该不会产生超卖现象了吧。
经实验,仍然产生了超卖现象。
因为虽然方法被锁住了,可是 @Transactional 注解 并没有及时的提交事务,导致库存没有及时扣减为0,因此还是超卖了。
3.3 正确使用事务的代码实现
@Autowired
private PlatformTransactionManager platformTransactionManager;
@Autowired
private TransactionDefinition transactionDefinition; // @Transactional(rollbackFor = Exception.class)
public synchronized void buy() { // 开启事务
TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition); try {
// 查看是商品否有库存
Integer count = getProductCount();
if(count <= 0) {
throw new RuntimeException("库存为 0");
} // 减库存
productRepository.reductCount(); // 生成订单
createOrder(); // 事务提交
platformTransactionManager.commit(transactionStatus);
} catch (Exception ex) {
log.error(ex.getMessage(), ex);
// 事务回滚
platformTransactionManager.rollback(transactionStatus);
} }
这次我们不使用 @Transactional 注解管理事务了,改为手动管理事务。
经实验,解决了超卖现象。
4. 综述
今天聊了一下 Springboot在有锁的情况下如何正确使用事务,希望可以对大家的工作有所帮助。
欢迎帮忙点赞、评论、转发、加关注 :)
关注追风人聊Java,每天更新Java干货。
Springboot在有锁的情况下如何正确使用事务的更多相关文章
- 2020-03-27:分布式锁的问题,假如a线程在获得锁的情况下 网络波动 极端情况是断网了,这种情况是怎么处理的
福哥答案2020-04-04:超时释放锁.
- laravel项目return back()->withErrors($validator)或return back()->with('errors','原密码错误!')在前台原密码错误的情况下不能正确显示错误信息,变成报错!
被折磨的答案是 php artisan --version看一下版本,如果是5.2.26以上的,在路由处删除web中间件分组,还有问题再反馈
- Eureka在有虚拟网卡的情况下获取正确的IP
发现问题 最近项目在Eureka注册时,发现一个问题:注册的IP地址不是 192.168.0.XXX 的网络IP,而是另外一个网段的地址,如图 通过 ipconfig 命令查看本机的IP地址发现,该I ...
- mysql什么情况下会触发表锁
锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算资源(如CPU.RAM.I/O等)的争用以外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是所有数 ...
- [数据库事务与锁]详解八:底理解数据库事务乐观锁的一种实现方式——CAS
注明: 本文转载自http://www.hollischuang.com/archives/1537 在深入理解乐观锁与悲观锁一文中我们介绍过锁.本文在这篇文章的基础上,深入分析一下乐观锁的实现机制, ...
- [MySQL数据库之事务、读现象、数据库锁机制、多版本控制MVCC、事务隔离机制]
[MySQL数据库之事务.读现象.数据库锁机制.多版本控制MVCC.事务隔离机制] 事务 1.什么是事务: 事务(Transaction),顾名思义就是要做的或所做的事情,数据库事务指的则是作为单个逻 ...
- mysql在生产环境下有大量锁表,又不允许重启的情况下的处理办法
mysql在生产环境下有大量锁表,又不允许重启的情况下的处理办法 满头大汗的宅鸟该怎么办呢? mysql -u root -e "show processlist"|grep -i ...
- java 哪些情况下会使对象锁释放
Java_多线程_锁释放 问:Java多线程运行环境中,在哪些情况下会使对象锁释放?答:由于等待一个锁的线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不再需要锁的时候及时释放锁是很重要的 ...
- Java高并发情况下的锁机制优化
本文主要讲并行优化的几种方式, 其结构如下: 锁优化 减少锁的持有时间 例如避免给整个方法加锁 1 public synchronized void syncMethod(){ 2 othercode ...
随机推荐
- spring初始化源码浅析之关键类和扩展接口
目录 1.关键接口和类 1.1.关键类之 DefaultListableBeanFactory 1.2.关键类之XmlBeanDefinitionReader 1.3.关键类之ClassPathXml ...
- 在Spring中使用静态工厂时发生的无法得到对象的问题
因为我测试时,使用的是之前的包Spring 3.x一类的jar包,发现我的代码毫无问题,但是就是运行不出来,后面去Spring官网上发现,JDK6+至少都要使用Spring4.x了,而为了配合JDK8 ...
- JDBC基础篇(MYSQL)——PreparedStatement执行DML、DQL等
注意:其中的JdbcUtil是我自定义的连接工具类:代码例子链接: package day03.prepare; import java.sql.Connection; import java.sql ...
- 使用Eclipse搭建SSM框架(Spring + Spring MVC + Mybatis)
1.创建项目 1)打开Eclipse,点击File --> New --> Other 2)输入maven,找到Maven Project 3)然后一直按Next,直到出现一下界面: 4) ...
- 五分钟搞定Docker安装ElasticSearch
前言 项目准备上ElasticSearch,为了后期开发不卡壳只能笨鸟先飞,在整个安装过程中遇到以下三个问题. Docker安装非常慢 ElasticSearch-Head连接出现跨域 Elastic ...
- i++ ++i 理解
i++与++i怎么运算,解决办法: i++规则是在表达式中先取i的值使用,后让i的值变化成加1后的值. 举例:如在式中 j=i++,他就会变成这样的两步,第一步先执行j=i,第二步执行i=i+1. + ...
- app自动化定位:UIautomation的用法
UIautomation定位的优点: 速度比xpath定位快,UIautomation是Android的工作引擎 缺点: 没有idea提示 UIautomation使用方法: AndroidDrive ...
- JS014. toFixed( )调试踩坑 - 浏览器思维 点常量 & 点运算符
Number.prototype.toFixed( ) 在观察toFixed()丢失精度问题,和对toFixed()方法重写的调试过程时,发现toFixed()对Number的识别有它自己的规则,并找 ...
- VUE003. 解决data中使用vue-i18n不更新视图问题(computed属性)
案例 在国际化开发中,有一部分需要国际化的文字是由数据驱动的储存在data中,然而VUE的data存在很多无法实时更新视图的问题,比如v-for循环的标签,当数据层次过深,通过源数据数组的索引改变它的 ...
- 分布式搜索引擎Elasticsearch在CentOS7中的安装
1. 概述 随着企业业务量的不断增大,业务数据随之增加,传统的基于关系型数据库的搜索已经不能满足需要. 在关系型数据库中搜索,只能支持简单的关键字搜索,做不到分词和统计的功能,而且当单表数据量到达上百 ...