spring事务+java锁机制

1 问题描述

最近再做火车票购票时,在对票类库存进行扣减,有线程安全的问题,遂加锁lock进行同步,

但发现加锁后并没有控制住库存线程安全的问题,导致库存仍被超发。

先简单介绍下,各层的技术架构:

中间层框架:SpringBoot
持久层:MyBatis
MVC框架:Spring MVC
存在问题的代码:

@Transactional
@Override
public List updateTables() {
//查询库存,根据库存判断是否具有购买资格,具有资格则更新库存
//其中mysql操作包含select和update
//更新trade,payment,插入tickets
}

理论情况具体描述:
当库存剩余为1时,线程1拿到锁进入同步代码块,扣减库存,线程2等待锁;
当线程1执行完同步代码块时,线程2拿到锁,执行同步代码块,检查到的库存剩余仍为0

2 排查问题
查找资料发现spring的事务引起的,因为Spring的@Transactional是AOP实现的,它是在函数开始前开启事务,在函数执行完毕后提交事务。所以上面代码中锁的释放是在事务提交之前,释放锁但是还未提交事务,所以另一个事务紧跟着执行,该事务查询的库存是还未提交的老数据。

3 解决方法
因为能力有限,所以目前的解决方法是将判断库存和更新的代码移动到controller中,不将他放在事务中,并且该代码中不使用事务

4总结
根据以上的排查过程,已经很清楚的确认了事务与锁之间存在的问题。由于事务范围大于锁代码块范围,在锁代码块执行完成后,此时事务还未提交,导致此时进入锁代码块的其他线程,读到的仍是原有的库存数据。

关于程序加锁自己的一点见解:

(1)建议程序中尽量不要加锁;
(2)如果使用锁,尽可能使用分布式锁
(3)使用锁的过程中,尽量减小锁粒度,尽量减小锁的代码范围;

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值