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在有锁的情况下如何正确使用事务的更多相关文章

  1. 2020-03-27:分布式锁的问题,假如a线程在获得锁的情况下 网络波动 极端情况是断网了,这种情况是怎么处理的

    福哥答案2020-04-04:超时释放锁.

  2. laravel项目return back()->withErrors($validator)或return back()->with('errors','原密码错误!')在前台原密码错误的情况下不能正确显示错误信息,变成报错!

    被折磨的答案是 php artisan --version看一下版本,如果是5.2.26以上的,在路由处删除web中间件分组,还有问题再反馈

  3. Eureka在有虚拟网卡的情况下获取正确的IP

    发现问题 最近项目在Eureka注册时,发现一个问题:注册的IP地址不是 192.168.0.XXX 的网络IP,而是另外一个网段的地址,如图 通过 ipconfig 命令查看本机的IP地址发现,该I ...

  4. mysql什么情况下会触发表锁

    锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算资源(如CPU.RAM.I/O等)的争用以外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是所有数 ...

  5. [数据库事务与锁]详解八:底理解数据库事务乐观锁的一种实现方式——CAS

    注明: 本文转载自http://www.hollischuang.com/archives/1537 在深入理解乐观锁与悲观锁一文中我们介绍过锁.本文在这篇文章的基础上,深入分析一下乐观锁的实现机制, ...

  6. [MySQL数据库之事务、读现象、数据库锁机制、多版本控制MVCC、事务隔离机制]

    [MySQL数据库之事务.读现象.数据库锁机制.多版本控制MVCC.事务隔离机制] 事务 1.什么是事务: 事务(Transaction),顾名思义就是要做的或所做的事情,数据库事务指的则是作为单个逻 ...

  7. mysql在生产环境下有大量锁表,又不允许重启的情况下的处理办法

    mysql在生产环境下有大量锁表,又不允许重启的情况下的处理办法 满头大汗的宅鸟该怎么办呢? mysql -u root -e "show processlist"|grep -i ...

  8. java 哪些情况下会使对象锁释放

    Java_多线程_锁释放 问:Java多线程运行环境中,在哪些情况下会使对象锁释放?答:由于等待一个锁的线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不再需要锁的时候及时释放锁是很重要的 ...

  9. Java高并发情况下的锁机制优化

    本文主要讲并行优化的几种方式, 其结构如下: 锁优化 减少锁的持有时间 例如避免给整个方法加锁 1 public synchronized void syncMethod(){ 2 othercode ...

随机推荐

  1. spring初始化源码浅析之关键类和扩展接口

    目录 1.关键接口和类 1.1.关键类之 DefaultListableBeanFactory 1.2.关键类之XmlBeanDefinitionReader 1.3.关键类之ClassPathXml ...

  2. 在Spring中使用静态工厂时发生的无法得到对象的问题

    因为我测试时,使用的是之前的包Spring 3.x一类的jar包,发现我的代码毫无问题,但是就是运行不出来,后面去Spring官网上发现,JDK6+至少都要使用Spring4.x了,而为了配合JDK8 ...

  3. JDBC基础篇(MYSQL)——PreparedStatement执行DML、DQL等

    注意:其中的JdbcUtil是我自定义的连接工具类:代码例子链接: package day03.prepare; import java.sql.Connection; import java.sql ...

  4. 使用Eclipse搭建SSM框架(Spring + Spring MVC + Mybatis)

    1.创建项目 1)打开Eclipse,点击File --> New --> Other 2)输入maven,找到Maven Project 3)然后一直按Next,直到出现一下界面: 4) ...

  5. 五分钟搞定Docker安装ElasticSearch

    前言 项目准备上ElasticSearch,为了后期开发不卡壳只能笨鸟先飞,在整个安装过程中遇到以下三个问题. Docker安装非常慢 ElasticSearch-Head连接出现跨域 Elastic ...

  6. i++ ++i 理解

    i++与++i怎么运算,解决办法: i++规则是在表达式中先取i的值使用,后让i的值变化成加1后的值. 举例:如在式中 j=i++,他就会变成这样的两步,第一步先执行j=i,第二步执行i=i+1. + ...

  7. app自动化定位:UIautomation的用法

    UIautomation定位的优点: 速度比xpath定位快,UIautomation是Android的工作引擎 缺点: 没有idea提示 UIautomation使用方法: AndroidDrive ...

  8. JS014. toFixed( )调试踩坑 - 浏览器思维 点常量 & 点运算符

    Number.prototype.toFixed( ) 在观察toFixed()丢失精度问题,和对toFixed()方法重写的调试过程时,发现toFixed()对Number的识别有它自己的规则,并找 ...

  9. VUE003. 解决data中使用vue-i18n不更新视图问题(computed属性)

    案例 在国际化开发中,有一部分需要国际化的文字是由数据驱动的储存在data中,然而VUE的data存在很多无法实时更新视图的问题,比如v-for循环的标签,当数据层次过深,通过源数据数组的索引改变它的 ...

  10. 分布式搜索引擎Elasticsearch在CentOS7中的安装

    1. 概述 随着企业业务量的不断增大,业务数据随之增加,传统的基于关系型数据库的搜索已经不能满足需要. 在关系型数据库中搜索,只能支持简单的关键字搜索,做不到分词和统计的功能,而且当单表数据量到达上百 ...