【事务与锁】当Transactional遇上synchronized

事务与锁 - Transactional与Synchronize🥰
- 前言
- 问题回放
- 问题一
- 1、代码与结果复现
- 2、原因分析
- 3、解决方法
- 问题二
- 1、问题复现
- 2、原因分析
- 事务Transactional与锁synchronized
- 1、synchronized与Transactional区别
- 2、可能带来的问题
- 3、针对问题二的解决
前言
最近工作中遇到某些七七八八的问题,就是与事务和锁、并发都有着紧密联系相关的问题所在。主要情况是:通过调用方法获取编号,而这个编号是递增有序的,并且存在于数据库中,简单理解就是需要用到这种编号(以下称任务编号),需要从数据库获取出来,在+1最为本次需要的编号,然后在存回数据库中,提供下次使用。直观来看是没得问题的,但是,可能在某次并发的时候出现编号相同,着属实很令人头疼,在经过领导的指导下是完美的解决了,接下来复盘一下。
问题回放
因为公司项目使用WQL作为持久层,但是我这次使用Mybatis-Plus,效果大差不差。新建springboot项目,基础创建不在赘述。主要创建一张简单的数据表,就一个id和number字段。之后用mp自动生成代码。
问题一
最外层加上Transactional注解,并且在对编码操作的方法也加了Transactional注解,为了防止并发问题,加了锁。此时模拟的问题是:在嵌套事务中,父事务延时提交导致获得到的数据出错。
1、代码与结果复现
直接在控制层中调用,这里会加上Transactional,并且一开始数据库数据为{“id”:“1”, “number”:“460”}
@GetMapping("/t1")
@Transactional(rollbackFor = Exception.class)
public void getTest1() {String n = countNumService.getCount();System.out.println(" t1 : " + n);try {Thread.sleep(6000);} catch (InterruptedException e) {throw new RuntimeException(e);}
}@GetMapping("/t2")
@Transactional(rollbackFor = Exception.class)
public void getTest2() {String n = countNumService.getCount();System.out.println(" t2 : " + n);// 忽略其他的增删操作
}
对数据库获取操作的方法,加上Transactional与synchronized。
@Override
@Transactional(rollbackFor = Exception.class)
public synchronized String getCount() {// 获取CountNum countNum = countNumMapper.selectById(1);countNum.setNumber(countNum.getNumber() + 1);// 修改countNumMapper.updateById(countNum);return countNum.getNumber().toString();
}
通过IDEA的插件RestServices(也可以用postman)测试,先请求/t1接口,这里会睡眠6s来模拟事务延时提交,在去请求/t2接口,可以看出得到的数据会是相同的。

2、原因分析
只有两个线程都能形成两个相同的code,仔细分析一下,假设synchronized锁是锁住的,那为什么会出现这样的问题呢?当t1线程访问getCount()方法,此时他拿到synchronized的锁,在进行获取数据并且+1操作后进行update操作,此时synchronized的锁已经被释放了,但是父事务却没有提交,也就是没有写回到数据库中,接下来t2线程过来了,也拿到了这把锁,又从数据库获取了数据,此时获得的是脏数据,最后就会导致出现了相同的code。

3、解决方法
这里是因为事务的先后提交导致,可以使用Transactional注解的配置来解决,使用@Transactional(propagation = Propagation.REQUIRES_NEW),每次都会启动一个新的事务,是Spring事务传播机制的一种级别,表示当前方法必须在自己的事务中运行,如果当前已经存在一个事务,则会挂起该事务,创建一个新的事务用于执行当前方法。当当前方法执行完成后,新事务被提交,原事务恢复执行。
问题二
此次测试是使用apache-jmeter-5.4.3测试工具来测试20次请求的并发情况(接口每次会创建100次,一共会又20*100次),在以上代码的条件下编写新的接口。
1、问题复现
以下是每次请求都会创建100个线程,getCount()除了使用propagation = Propagation.REQUIRES_NEW,其他不变。
@GetMapping("/t3")
@Transactional(rollbackFor = Exception.class)
public void getTest1() {for (int i = 0; i <100 ; i++) {new Thread(()->{String taskCode = countNumService.getCount();System.out.println("t1 " + Thread.currentThread().getName() + " code: " + taskCode);}).start();}
}
测试结果就会发现并发下出现了种种问题,会出现相同的code。

2、原因分析
这是由于父子事务嵌套,子事务与锁一起使用,导致了synchronized锁的失效。当我把事务去掉的时候,则就不会出现并发的问题。

问题就是出在事务与synchronized锁的共同使用导致的,如果既要保证并发不出问题,又要保证在异常的时候需要回滚数据,在实际应用中,getCount()内部又其他对数据库的操作,因此需要事务来保证异常的回滚,也就是一定需要父子事务的嵌套,在这种情况下需要怎么做处理?
首先先来了解事务Transactional与锁synchronized一同使用会带来什么问题。
事务Transactional与锁synchronized
事务Transactional与锁synchronized他们是两种不一样的机制,两种机制要是一起使用,可能会出现一些问题。
1、synchronized与Transactional区别
首先,synchronized锁是用来实现线程同步,防止多个线程同时访问共享资源导致的并发问题。而Transactional是Spring框架中用于管理事务的机制,用于保证多个操作的四个特性(原子性、一致性、隔离性和持久性)。
2、可能带来的问题
- 事务可能被锁定:如果在一个方法中使用synchronized锁定了某个共享资源,同时该方法又使用了Transactional来管理事务,那么其他线程在访问该方法时可能会被阻塞,因为事务被锁定了。
- 死锁问题:如果在多个线程中同时使用synchronized和Transactional,可能会导致死锁问题,因为synchronized锁定的资源可能被多个线程同时访问,而Transactional又会对这些操作进行管理,可能会导致事务的死锁。
- 性能问题:如果在一个高并发的系统中同时使用synchronized和Transactional,可能会导致性能问题,因为synchronized会导致线程阻塞,而Transactional又会增加事务的开销,从而影响系统的性能。
3、针对问题二的解决
可以将子事务中的锁移到父事务中,优化一下细粒度,就只对获取任务编码的这条语句进行上锁。
@GetMapping("/t4")
@Transactional(rollbackFor = Exception.class)
public void getTest4() {for (int i = 0; i <100 ; i++) {new Thread(()->{synchronized(CountNumController.class) {String taskCode = countNumService.getCount();System.out.println("t4 " + Thread.currentThread().getName() + " code: " + taskCode);}}).start();}
}
这样就能保证并发不出问题,也能保证将父子事务都存在。

👍创作不易,如有错误请指正,感谢观看!记得点赞哦!👍
相关文章:
【事务与锁】当Transactional遇上synchronized
事务与锁 - Transactional与Synchronize🥰前言问题回放问题一1、代码与结果复现2、原因分析3、解决方法问题二1、问题复现2、原因分析事务Transactional与锁synchronized1、synchronized与Transactional区别2、可能带来的问题3、针对问题二的解决前言 最近工作中遇…...
Pytorch模型转TensorRT步骤
Pytorch模型转TensorRT步骤 yolov5转TRT 流程 当前项目基于yolov5-6.0版本,如果使用其他版本代码请参考 https://github.com/wang-xinyu/tensorrtx/tree/master/yolov5 获取转换项目: git clone https://github.com/wang-xinyu/tensorrtx.git git …...
产品经理入门——必备技能之【产品运营】
文章目录一、基础介绍1.1 用户生命周期 & 产品生命周期1.2 运营的目的1.3 运营的阶段1.4 运营的主要工作(海盗模型)二、AARRR模型2.1 Acquisition 拉新2.2 Activision 促活2.3 Retention 留存2.4 Revenue 转化2.5 Referral 传播总结产品运营技能是产…...
【Java实现文件上传】java后端+vue前端实现文件上传全过程详解(附源码)
【写在前面】其实这篇文章我早就想写了,只是一直被需求开发耽搁,这不晚上刚好下班后有点时间,记录一下。需求是excel表格的上传,这个是很多业务系统不可或缺的功能点,再此也希望您能够读完我这篇文章对文件上传不再困惑…...
什么是SSD?SSD简述
什么是SSD?SSD简述前言一. SSD组成二. SSD存储介质存储介质按材料不同可分为三大类:光学存储介质、半导体存储介质和磁性存储介质三. SSD接口形态固态硬盘有SATA 3.0接口、MSATA接口、M.2接口、PCI-E接口、U.2接口五种类型。三. SSD闪存颗粒分类闪存颗粒…...
MySQL基础------sql指令1.0(查询操作->select)
目录 前言: 单表查询 1.查询当前所在数据库 2.查询整个表数据 3.查询某字段 4.条件查询 5.单行处理函数(聚合函数) 6.查询时给字段取别名 7.模糊查询 8.查询结果去除重复项 9.排序(升序和降序) 10. 分组查询 1…...
Python数据分析处理报告--实训小案例
目录 1、实验一 1.1、题目总览 1.2、代码解析 2、实现二 2.1、题目总览 2.2、代码解析 3、实验三 3.1、题目总览 3.2、代码解析 4、实验四 3.1、题目总览 3.2、代码解析 哈喽~今天学习记录的是数据分析实训小案例。 就用这个案例来好好巩固一下 python 数据分析三…...
OpenCV入门(十二)快速学会OpenCV 11几何变换
OpenCV入门(十二)快速学会OpenCV 11几何变换1.图像平移2.图像旋转3.仿射变换4.图像缩放我们在处理图像时,往往会遇到需要对图像进行几何变换的问题。图像的几何变换是图像处理和图像分析的基础内容之一,不仅提供了产生某些图像的可…...
小菜鸟Python历险记:(第二集)
今天写的文章是记录我从零开始学习Python的全过程。Python基础语法学习:Python中的数值运算一共有7种,分别是加法()、减法(-)、除法(/)得到的结果是一个浮点数、乘法(*&a…...
ContentProvider程序之间数据的相互调用
1权限的获取和调用 权限分为普通权限和危险权限,除了日历信息,电话,通话记录,相机,通讯录,定位,麦克风,电话,传感器,界面识别(Activity-Recognit…...
金三银四最近一次面试,被阿里P8测开虐惨了...
都说金三银四涨薪季,我是着急忙慌的准备简历——5年软件测试经验,可独立测试大型产品项目,熟悉项目测试流程...薪资要求?5年测试经验起码能要个20K吧 我加班肝了一页半简历,投出去一周,面试电话倒是不少&a…...
算法题——给定一个字符串 s ,请你找出其中不含有重复字符的最长子串 的长度
给定一个字符串 s ,请你找出其中不含有重复字符的最长子串 的长度 示例 1: 输入: s “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。 示例 2: 输入: s “bbbbb” 输出: 1 解释: 因为无重复字符的最长子串是 “b”&am…...
机器学习中的数学原理——F值与交叉验证
通过这篇博客,你将清晰的明白什么是F值、交叉验证。这个专栏名为白话机器学习中数学学习笔记,主要是用来分享一下我在 机器学习中的学习笔记及一些感悟,也希望对你的学习有帮助哦!感兴趣的小伙伴欢迎私信或者评论区留言࿰…...
vue.js介绍
个人名片: 😊作者简介:一名大一在校生,web前端开发专业 🤡 个人主页:python学不会123 🐼座右铭:懒惰受到的惩罚不仅仅是自己的失败,还有别人的成功。 🎅**学习…...
【设计模式】1、设计模式七大原则
目录一、单一职责二、接口隔离三、依赖倒置(倒转)四、里氏替换五、迪米特法则(Law of Demeter)六、开闭七、合成复用一、单一职责 类(或方法)功能的专一性。一个类(或方法)不应该承担…...
【前端老赵的CSS简明教程】10-1 CSS预处理器和使用方法
大家好,欢迎来到本期前端课程。我是前端老赵,今天的课程将讲解CSS预处理器的概念和使用方法,希望能够帮助大家更好地进行前端开发。 CSS预处理器是什么? CSS预处理器是一种将类似CSS的语言转换为CSS的工具。它们提供了许多额外的功能,如变量、嵌套、混入、函数等等。这些…...
BFC详解
1. 引言 在前端的布局手段中,一直有这么一个知识点,很多前端开发者都知道有它的存在,但是很多人也仅仅是知道它的存在而已,对它的作用也只是将将说得出来,可是却没办法说得非常的清晰。这个知识点,就是BFC…...
C++:哈希结构(内含unordered_set和unordered_map实现)
unordered系列关联式容器 在C98中,STL提供了底层为红黑树结构的一系列关联式容器,在查询时效率可达到$log_2 N$,即最差情况下需要比较红黑树的高度次,当树中的节点非常多时,查询效率也不理想。最好 的查询是ÿ…...
Java实现调用第三方相关接口(附详细思路)
目录1.0.简单版2.0.升级版2-1.call.timeout()怎么传入新的超时值2-2.timeout(10, TimeUnit.SECONDS)两个参数的意思,具体含义3.0.进阶版3-1.java.net.SocketTimeoutException: 超时如何解决4.0.终极版1.0.简单版 以下是一个使用 Java 实际请求“第三方”的简单示例代…...
基础数据结构:单链表
今天懒洋洋学习了关于基础数据结构有关单链表的相关操作,懒洋洋来这温习一下。一:单链表的定义链表定义:用链式存储的线性表统称为链表,即逻辑结构上连续,物理结构上不连续。链表分类:单链表、双链表、循环链表、静态链…...
117.YOLOv5/v8数学原理+CSPDarknet架构,CUDA117环境一键部署
摘要 YOLO(You Only Look Once)系列算法是目标检测领域最主流的实时检测框架,其核心思想是将目标检测任务转化为一个端到端的回归问题。 本文从数学原理出发,系统阐述YOLOv5/v8的架构演进与核心机制,并提供一个从数据准备、模型训练到ONNX部署的完整可运行案例。 文章所有…...
归并排序:分治思想的经典应用
归并排序一、核心原理分治思想分:把数组不断从中间拆成左右两半,直到每个子数组只剩 1 个元素(天然有序);治:把两个有序子数组 合并 成一个大的有序数组;递归向上合并,最终整个数组有…...
ComfyUI-Impact-Pack完全指南:如何彻底解决AI图像细节增强难题
ComfyUI-Impact-Pack完全指南:如何彻底解决AI图像细节增强难题 【免费下载链接】ComfyUI-Impact-Pack Custom nodes pack for ComfyUI This custom node helps to conveniently enhance images through Detector, Detailer, Upscaler, Pipe, and more. 项目地址: …...
从90%到99%:实战提升Tesseract在C++项目中的识别准确率(附调参技巧)
从90%到99%:实战提升Tesseract在C项目中的识别准确率(附调参技巧) 在工业级文档处理系统中,我们常遇到这样的困境:测试集上的OCR识别准确率卡在90%左右,而业务部门要求必须达到99%以上才能上线。去年负责某…...
天赐范式第37天:从手机端AI工具的疯狂质疑,到AI电脑端天赐范式的群策群力,为自身提供了源源不断的自驱动力
当3个AI客户端和一个人类(天赐范式),被自己的AI手机端说成是人类的共犯。 参与主体:手机端文心,手机端DEEPSEEK,文章DEEPSEEK(主理),豆包全场看戏。 摘要:手…...
终极免费跨平台待办清单:My-TODOs 让您的任务管理回归简单高效
终极免费跨平台待办清单:My-TODOs 让您的任务管理回归简单高效 【免费下载链接】My-TODOs A cross-platform desktop To-Do list. 跨平台桌面待办小工具 项目地址: https://gitcode.com/gh_mirrors/my/My-TODOs 在信息爆炸的时代,我们每天都在处理…...
告别虚拟机臃肿:用QEMU用户模式(qemu-user)快速运行跨架构程序的完整指南
告别虚拟机臃肿:用QEMU用户模式(qemu-user)快速运行跨架构程序的完整指南 在开发跨平台应用或研究嵌入式系统时,开发者经常需要处理不同CPU架构的二进制文件。传统解决方案是启动完整的虚拟机,但这会消耗大量系统资源&…...
3个技巧彻底改变你的泰坦之旅装备管理体验
3个技巧彻底改变你的泰坦之旅装备管理体验 【免费下载链接】TQVaultAE Extra bank space for Titan Quest Anniversary Edition 项目地址: https://gitcode.com/gh_mirrors/tq/TQVaultAE 你是否曾在泰坦之旅的冒险中,面对满仓库的传奇装备却找不到需要的那一…...
LDO噪声特性分析与测量优化指南
1. LDO噪声特性与测量基础低噪声线性稳压器(LDO)作为电源管理系统的核心器件,其噪声特性直接影响着精密模拟电路、射频系统和传感器等关键模块的性能表现。与开关电源不同,LDO通过线性调节方式工作,避免了高频开关噪声…...
主流AI培训课程对比:五大选型维度实务评测
1. 引言:从技术焦虑到价值落地的“最后一公里”随着生成式AI技术,特别是Sora2、Runway等视频生成模型,以及GPT-4o、文心一言等多模态大模型的快速迭代,企业数字化转型与个人技能升级的迫切需求从未如此强烈。然而,市场…...
