您的位置 首页 > 教育学习

Transcational与Synchronized或Lock搭配使用导致并发问题 Transcat软件

Transcational与Synchronized或Lock搭配使用导致并发问题

在多线程的情况下,我们经常会用到synchronized或者Lock来保证我们的线程安全。 但是当碰到Transcational之后又会碰撞出什么火花呢?

相信我,看完之后,你一定不会亏

首先回顾一下小知识点: 基于@Transactional注解的是 声明式事务 spring还提供了另外一种创建事务的方式,即通过手动编写代码实现的事务,我们把这种事务叫做:编程式事务。

数据库连接本来默认是自动提交的,加上注解Transactional之后,会设置为手动提交。 自动提交意味着 每当我们执行一个update ,delete或者insert的时候都会自动提交到数据库,无法回滚事务。

下面我们来看一个例子: 这个方法的执行流程是这样的。 很显然,涉及库存和订单,都会对数据库进行操作,且应该是应该原子性的操作。

所以我们在方法上加了一个 @Transactional 注解。

接着我们用Jmeter进行并发测试 15个线程 抢购数据库现有的10个库存。 执行完之后,我们发现本来10台库存,现在15个人居然都抢到了,还剩了2台。 真是离谱Mother给离谱开门,离谱到家了。此刻我真的想说,I love you Mother。

本来我们想象的执行流程应该是这样的:

造成现在超卖这种情况,只能说明我们的执行流程是这样的。

原因就在于,加上Transactional 之后,代码执行顺序变成了,先执行开启了事务,然后在上锁。最后的时候先解锁,然后提交事务。 在解锁和提交事务这个间隙中,使得其他线程有了趁虚而入的机会。上一个线程还没提交事务呢,下一个线程已经进来了,并且读取到的库存数量还是上一个线程修改之前的库存量。

所以,正确的使用锁:把整个事务放在锁的工作范围之内。即在进入事务方法之前就加上锁。

因此,我们可以这样解决: 想这样解决的朋友,回去等通知吧。赶紧去搜一下事务失效的几种场景

正常使用的话,可以这样: 第一种: 新建一个service,将之前lock锁之后的代码逻辑,放到另外一个service方法当中,然后再进行调用。

第二种:自己注入自己的方式

同样的,如果使用synchronized的话,也会出现同样的问题。 解决方案参考上面的方式,也可以这样。 参考文章 歪歪大神 https://juejin.cn/post/6999476143699001352#heading-3

责任编辑: 鲁达

1.内容基于多重复合算法人工智能语言模型创作,旨在以深度学习研究为目的传播信息知识,内容观点与本网站无关,反馈举报请
2.仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证;
3.本站属于非营利性站点无毒无广告,请读者放心使用!

“Transcational与Synchronized或Lock搭配使用导致并发问题”边界阅读