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 ...
随机推荐
- JAVA中多态与C++多态的区别
原文出自:http://blog.csdn.net/hihui/article/details/8604779 #include <stdio.h> class Base { public ...
- 高德地图——2D转换3D
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script ty ...
- 根据经纬度查询最近距离,mysql查询经纬度附近范围
public class Test{ private static List<LocalAddress> ilist = new ArrayList<LocalAddress> ...
- python--接口自动化经常用到的pytest框架
pytest常用的方法和原理 1.pytest的原理 pytest插件基于pluggy模块:pluggy有三个重要概念:HookspecMarker(用来定义hook函数),HookimplMarke ...
- GoLang设计模式01 - 建造者模式
建造者模式是一种创建型模式,主要用来创建比较复杂的对象. 建造者模式的使用场景: 建造者模式通常适用于有多个构造器参数或者需要较多构建步骤的场景.使用建造者模式可以精简构造器参数的数量,让构建过程更有 ...
- Vs code自动生成Doxygen格式注释
前言 程序中注释的规范和统一性的重要性不言而喻,本文就推荐一种在用vscode编写代码时自动化生成标准化注释格式的方法,关于Doxygen规范及其使用可查看博文 代码注释规范之Doxygen. ...
- python3 爬虫五大模块之五:信息采集器
Python的爬虫框架主要可以分为以下五个部分: 爬虫调度器:用于各个模块之间的通信,可以理解为爬虫的入口与核心(main函数),爬虫的执行策略在此模块进行定义: URL管理器:负责URL的管理,包括 ...
- npm 淘宝镜像与官方源 切换
1.临时使用 npm --registry https://registry.npm.taobao.org install 包名 2.永久设置为淘宝镜像 npm config set registry ...
- 使用Apache poi来编写导出excel的工具类
在JavaWeb开发的需求中,我们会经常看到导出excel的功能需求,然后java并没有提供操作office文档的功能,这个时候我们就需要使用额外的组件来帮助我们完成这项功能了. 很高兴Apache基 ...
- 知乎vscode插件修改和重新编译
需求来源 vscode插件修改代码要怎样重新编译并安装到vscode中? 起源于我使用一个vscode插件,它可以在vscode中发布文章到知乎上,然后我修改了插件的部分源代码,希望在vscode中安 ...