一种常见的并发问题处理

分享一种非常常见的并发问题处理,先看下场景重现:
在这个并发场景中,有一下几个条件

  • 使用了spring的@transactional注解处理事务,
  • 在A方法调用了B方法,A和B在同一个service方法中,同时A和B方法都使用了REQUIRED的传播方式
  • 在b方法中,先判断数据库中是否有记录,有则修改,无则添加。

好了,这个方法在使用jmeter测试时,就会有很大概率,无视b方法中的判断方法,往数据库中添加数据了。。
为什么呢,思考了一下,感觉有两个原因

  • 两个线程同时进入B方法,则在查询数据库时都查询不到记录,自然都走添加记录的方法了。
  • 第二个线程在查询时,第一个线程的事务还没有提交(因为使用REQUIRED的传播方式,导致线程1虽然数据insert的方法执行了,但是spring 事务并没有提交,还在等后续方法执行)。

我的解决方案主要记录如下

添加lock锁,在A方法开始加锁,在finally中解锁。示例代码在下面:

lock.lock();
try {
    B b = applicationContext.getBean(B.class);
    b.xxx(xxx);
} finally {
    lock.unlock();
}

但是还不行,因为原因2,导致整体事务没提交,查询的时候还是查不到,所以,我将方法B的事务传播方法改成REQUIRES_NEW,使方法B在操作完数据库就立即提交,但是 方法A和B又在同一个service中,而在spring中,
如果A和B在统一service中,A直接调用B,则B的事务不起作用 ,所以我使用applicationContext.getBean(B.class)获取到b,再去调用b的xxx方法,测试,问题解决。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值