@Transactional注解方法下synchronized失效问题

在Spring中,@Transactional注解可能导致synchronized锁失效,引发并发问题。当多个线程在事务中访问数据库时,可能会读取到旧值,导致数据不一致。解决方案包括手动提交事务或在调用方法级别加锁。注意锁的作用范围,以避免并发场景下预期结果与实际不符。

问题:

开发过程中遇到一个坑,@Transactional注解方法下synchronized失效问题。

 

代码如下:

package com.example.demo.service.impl;

import com.example.demo.mapper.MoneyMapper;
import com.example.demo.model.po.MoneyPo;
import com.example.demo.model.vo.TrandingVo;
import com.example.demo.service.MoneyService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import lombok.extern.slf4j.Slf4j;

/**
 * @Author: yipeng
 * @Date: 2021/6/18 21:09
 */
@Service
@Slf4j
public class MoneyServiceImpl implements MoneyService {

    @Autowired
    private MoneyMapper moneyMapper;


    @Override
    @Transactional
    public synchronized boolean trading(TrandingVo trandingVo) {
        MoneyPo fromUser = moneyMapper.getOneByUserName(trandingVo.getFromUserName());
        MoneyPo toUser = moneyMapper.getOneByUserName(trandingVo.getToUserName());
        if (fromUser.getMoney() > trandingVo.getMoney()) {
            fromUser.setMoney(fromUser.getMoney() - trandingVo.getMoney());
            toUser.setMoney(toUser.getMoney() + trandingVo.getMoney());
            moneyMapper.update(fromUser);
            moneyMapper.update(toUser);
            return true;
        }
        log.error("trading error" + Thread.currentThread().getName());
        return false;
    }
}

 

现象:

1. synchronized锁trading函数还是锁trading函数中代码块,锁都失效

2. ReentrantLock锁trading函数中代码块也无济于事

3. redis分布式锁用于trading函数设想应该也无济于事

 

原因:

锁释放了,但事务却没提交。

并发场境下,出现多个线程拿到的数据库旧值而非最新值的现象,进而导致多线程安全bug。

 

解决方法:

1. 手动提交事务(不提倡)

2. 锁加在调用trading函数方法的上一级代码中

 

结论:

使用锁时候,注意锁的作用范围,诸如@Transactional或其他自定义的功能性注解,要注意锁作用域不全导致并发情况下与预期结果不一致的情况。

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

益朋

看官老爷们的打赏是我前进的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值