当前位置: 首页 > news >正文

@Transactional和synchronized同时使用时的一些问题以及解决

@Transactional和synchronized同时使用并不能保证事务一致性

背景

任何事情都有一个发生背景
有个需求【一个业务里面包含多个事务,而且还需要避免其他线程的影响,所幸的是该服务只需要启动单实例,不然还要考虑分布式的影响】
我的思路就是用@Transactional 和 synchronized来保证事务一致性和多线程影响,结果发现并没有如愿

分析原因

    @Transactionalpublic ResultVo service(){synchronized (LOCK){//doservice}}
关于为什么不是用synchronized 关键字而是使用代码块锁是为了不影响其他方法,关键字默认锁的是当前类对象
一开始我的代码是这样的,乍一看好像没什么问题,但是为什么会出问题呢

排查问题

问题重现 : 一定要重现问题,任何重现不了的问题都不是问题,任何存在的问题都必能重现
由近到远 : 先确认自己的代码没问题,再考虑外部代码(如二方库,三方库)
从内到外 : 程序本质就是IPO,包含输入(input),程序(program)/指令集,输出(output),先确认输入没有问题,再确认代码逻辑
由浅入深 : 从易到难,从上到下,先上层API,http传输等,再底层API,源码,jvm等

说到这里,问题就比较容易分析了

首先我的输入没有问题

其次我逻辑代码也没有问题

接下来就是二方库和三方库了

由于事务用的是spring的事务,是基于aop实现的,ok找到问题了

由于spring的aop,会在@Transactional修饰的方法之前开启事务,之后再加锁,当锁住的代码执行完成后,在提交事务,
因此synchronized代码块执行是在事务之内执行的,可以推断在代码块执行完时,事务还未提交,其他线程进入synchronized代码块后,读取的库存数据不是最新的。

解决问题

在网上看到很多解决方案都在说在外层套一个方法,把锁的级别提高,或则说在controller加锁
这样可能会导致事务不会回滚
spring事务管理中,使用Synchronized修饰事务方法,同步为什么会失效
https://blog.csdn.net/weixin_54401017/article/details/129768305
这里提供一个解决方案,利用线程池,当然业务代码还是要加@Transactional的!!!
private ExecutorService executorService = null;//线程池public ResultVo updateOk(@RequestBody OtcTransferOutManageVo otcTransferOutManageVo){//如果线程池为null或则线程池被关闭了,创建一个单线程化线程池if (executorService == null || executorService.isShutdown()) {executorService = Executors.newSingleThreadExecutor();}if (otcTransferOutManageVo.getId() == null) {return ResultVoBuildUtils.buildResultVo( Constants.FAIL, "参数错误" );}//使用submit执行业务  Future和result.get()是为了保障线程同步,不然变成异步线程是无法捕获异常信息的Future<ResultVo> result = executorService.submit(()->{ResultVo resultVo = otcTransferOutManageService.updateOkStatus(otcTransferOutManageVo);LoggerHepler.writeInfoLog( TransferInController.class, resultVo.getMsg() );return resultVo;});executorService.shutdown();try {return result.get();} catch (Exception e) {LoggerHepler.writeErrorLog( TransferOutManageController.class, ServiceTypeENUM.ASSET_MANAGEMEN, BusinessTypeENUM.TRADE,ExceptionCodeConstants.UPDATE_MYSQL_EXCEPTION, "updateOk error!", e );return ResultVoBuildUtils.buildFaildResultVo();}}
关于这段代码有几点需要说一下

newSingleThreadExecutor()创建单线程化的线程池

通过源码可以看到 :
该方法创建一个单一工作线程的线程池,如果此线程在执行过程中失败了,会有一个新的线程来继续完成未完成的工作
任务会被保证是顺序执行的(串行),并且再任意时间都不会超过一个活跃线程
这里基于的是LinkedBlockingQueue,这是一个线程安全的阻塞队列

shutdown()方法

在调用这个方法后,会在submit的任务执行完成后将线程池变为shutdown状态,拒绝新的任务(线程池不会立刻退出,直到任务完成)
如果已经关闭了,调用此方法也不会有额外的影响
此时不能再往线程池中添加新任务,否则会抛出RejectedExecutionException异常。
  • Future && get()

因为这里需要获取线程执行的返回值,
无论是继承Thread类还是实现Runnable接口都无法获取到线程执行的返回值(默认是异步线程)
所以这里用到的是线程的第三种创建方式,实现callable接口重写call方法,当然重写call方法被我用lambda表达式隐含了
所以get()就是为了获取线程执行的返回值

submit()方法

传入一个Callable 任务,返回执行完成的返回值

相关文章:

@Transactional和synchronized同时使用时的一些问题以及解决

Transactional和synchronized同时使用并不能保证事务一致性背景任何事情都有一个发生背景有个需求【一个业务里面包含多个事务,而且还需要避免其他线程的影响,所幸的是该服务只需要启动单实例,不然还要考虑分布式的影响】我的思路就是用Transactional 和 synchronized来保证事务…...

贪心-根据身高重建队列

假设有打乱顺序的一群人站成一个队列&#xff0c;数组 people 表示队列中一些人的属性&#xff08;不一定按顺序&#xff09;。每个 people[i] [hi, ki] 表示第 i 个人的身高为 hi &#xff0c;前面 正好 有 ki 个身高大于或等于 hi 的人。 请你重新构造并返回输入数组 peopl…...

「解析」牛客网-华为机考企业真题 21-40

又是一年春招时&#xff0c;有幸收到华为自动驾驶算法岗&#xff0c;之前刷题不多&#xff0c;在此汇总下牛客网的真题&#xff0c;主要采用Python编写&#xff0c;个人觉得语言只是实现工具而已&#xff0c;并不是很关键&#xff0c;Python简洁易懂&#xff0c;更加适合算法工…...

JAVA练习92-快乐数

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 3月28日练习内容 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、题目-…...

BPF 之路:技术背景

目录 引言 什么是BPF 历史 组成 执行机制 BPF 和ebpf 的关系 BCC、bpftrace、IO Visor BCC 项目的quick start execsnoop biolatency 动态插桩&#xff1a;kprobes和uprobes 概念 缺点 静态插桩&#xff1a;tracepoint 和USDT 概念 缺点 推荐的方案 初识bpft…...

C++—— set、map、multiset、multimap

目录 关联式容器 概念 键值对 树形关联式容器 set 介绍 定义方式 使用 map 介绍 使用 multiset 介绍 使用 multimap 介绍 使用 相关的OJ题 前K个高频单词 关联式容器 概念 我们之前接触过的一些容器&#xff0c;比如&#xff1a;vector、list、deque、forwa…...

Qlib使用

Qlib https://github.com/microsoft/qlib 将csv文件转化为Qlib的数据格式&#xff1a;https://qlib.readthedocs.io/en/latest/component/data.html#converting-csv-format-into-qlib-format 注意每支股票都要保存成单独一个文档&#xff0c;且文档名字与股票代号一致。 其中f…...

TL-WDR7660 httpProcDataSrv任意代码执行漏洞复现分析

01 漏洞简述 2023年1月31日&#xff0c;CNVD公开了一个由国内安全研究员提交的TL-WDR7660 httpProcDataSrv任意代码执行漏洞&#xff0c;编号为CNVD-2023-05404&#xff0c;同时公开了漏洞利用详情&#xff0c;poc代码链接为https://github.com/fishykz/TP-POC。从poc代码详情…...

基于DDS的SOA测试方案实现

随着以太网技术在车载网络中的应用&#xff0c;各种基于以太网的中间件也相继被应用在车内&#xff0c;如果对车载网络有过相关了解的小伙伴&#xff0c;对于作为中间件之一的DDS&#xff08;数据分发服务Data Distribution Service&#xff09;可能并不陌生&#xff1b;若没有…...

LibTorch中Windows系统环境配置及CUDA不可用问题解决

前言&#xff1a;本文对在Windows系统上进行LibTorch开发环境配置及相关问题解决做一个较为详细的记录&#xff0c;以便后续查询使用。 使用环境版本&#xff1a; Windows 11 Visual Studio 2022 CUDA 12.0 LibTorch 1.13.1_cu11.7 目录一、LibTorch简介二、LibTorch下载安装三…...

Java并发编程实战二

线程间的通讯方式 1.volitate(缓存一致性协议),synchronize,lock(都保证可见性) 2.wait.notify,await(),signal(前两个是Object&#xff0c;后两个属于lock) 3.管道输入、输出流 (示例代码&#xff1a;PipeInOut.java)&#xff08;目前几乎没人使用&#xff09; 管道输入/输…...

Linux中最基本的命令ls的用法有哪些?

Linux是一种流行的操作系统&#xff0c;被广泛应用于服务器和个人电脑。Linux命令行界面是使用Linux操作系统的关键。其中一个最基本的命令是"ls"命令&#xff0c;该命令用于列出指定目录中的所有文件和子目录。在这篇文章中&#xff0c;我们将探讨ls命令及其各种用途…...

第 100002(十万零二)个素数是多少?

题目描述 素数就是不能再进行等分的整数。比如7&#xff0c;11。而 9 不是素数&#xff0c;因为它可以平分为 3 等份。一般认为最小的素数是2&#xff0c;接着是 3&#xff0c;5&#xff0c;... 请问&#xff0c;第 100002(十万零二)个素数是多少&#xff1f; 请注意&#xff1…...

Lua迭代器

Lua迭代器 迭代器&#xff08;iterator&#xff09;是一种对象&#xff0c;它能够用来遍历标准模板库容器中的部分或全部元素&#xff0c;每个迭代器对象代表容器中的确定的地址。 在 Lua 中迭代器是一种支持指针类型的结构&#xff0c;它可以遍历集合的每一个元素。 泛型 f…...

同步与互斥之信号量

目录 1、信号量用于线程的互斥 验证 2、信号量用于线程的同步 验证 3、无名信号量用于进程间互斥 代码一 代码二 验证 4、有名信号量 用于进程间同步和互斥 验证 信号量广泛用于进程或线程间的同步和互斥&#xff0c;信号量本质上是一个非负的整数计数器&#xff0c;它…...

如何当个优秀的文档工程师?从 TC China 看技术文档工程师的自我修养

本文系 NebulaGraph Community Academic 技术文档工程师 Abby 的参会观感&#xff0c;讲述了她在中国技术传播大会分享的收获以及感悟。 据说&#xff0c;技术内容领域、传播领域的专家和决策者们会在中国技术传播大会「tcworld China 2022」大会上分享心得。作为一名技术文档工…...

如何学习k8s

学习Kubernetes可以遵循以下步骤&#xff1a; 了解Kubernetes的基本概念和架构。学习Kubernetes前&#xff0c;需要了解它的基本概念和组成部分&#xff0c;包括Pod、Service、ReplicaSet、Deployment、Namespace等等&#xff0c;同时也需要了解Kubernetes的整体架构和工作原理…...

【SSM】MyBatis(十.动态sql)

文章目录1.if2.where3.trim4.set5. choose when otherwise6.foreach6.1 批量删除6.2 批量增加7.sql1.if <select id"selectByMultiCondition" resultType"Car">select * from t_car where 1 1<if test"brand ! null and brand ! ">…...

最近很多人都在说 “前端已死”,讲讲我的看法

转自 : 掘金 作者 : Ethan_Zhou 现状 我记得去年脉脉的论调还都是 客户端已死&#xff0c;前后端还都是一片祥和&#xff0c;有秀工资的&#xff0c;有咨询客户端转前端的&#xff0c;怎么最近打开脉脉一看&#xff0c;风向变了&#xff1f; 随便刷几下&#xff0c;出来的信息…...

大家好,我是火旺技术

大家好&#xff0c;我是火旺技术 在Internet高速发展的今天&#xff0c;我们生活的各个领域都涉及到计算机的应用。这其中&#xff0c;家乡特色推荐的网络应用已经成为外国家乡推荐系统的一种很普遍的方式。不过&#xff0c;在国内&#xff0c;管理网站可能还处于起步阶段。 …...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

Spring Boot 实现流式响应(兼容 2.7.x)

在实际开发中&#xff0c;我们可能会遇到一些流式数据处理的场景&#xff0c;比如接收来自上游接口的 Server-Sent Events&#xff08;SSE&#xff09; 或 流式 JSON 内容&#xff0c;并将其原样中转给前端页面或客户端。这种情况下&#xff0c;传统的 RestTemplate 缓存机制会…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

Fabric V2.5 通用溯源系统——增加图片上传与下载功能

fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...