关于 在springboot项目中生成流水号之类的业务时 添加 synchronized同步代码块无效

该博客讨论了一种简单的流水号生成代码,在实际运行中出现重复的问题。问题源于@Transactional注解与synchronized关键字的不当结合,由于@Transactional基于动态代理实现事务,导致线程安全性受影响。解决方法是避免在同一方法上同时使用这两个特性。
摘要由CSDN通过智能技术生成

一个简单的获取流水号代码:

/**
	 * 获取流水号
	 * @param billstype 业务类型
	 * @return
	 */
	@Transactional(rollbackFor = Throwable.class)
	public synchronized int getOrUpdateNumber(String billstype) {
        int num = 1;
        //获取历史流水号
        Stream stream = streamDao.getStreamBySource(billstype);
        if(stream!=null){
			//流水位
			String data_num = stream.getStreamId();
            num = Integer.parseInt(data_num);
            stream.setStreamId((num + 1)+"");
            streamDao.updateStreamBySource(stream);
        }else{
        	Stream streamInfo = new Stream();
        	streamInfo.setSource(billstype);
        	streamInfo.setStreamId((num + 1)+"");
        	streamDao.createStream(streamInfo);
        }
        return num;
    }

咋一看应该是没有什么问题的,可是在实际使用过程中却出现了重复的情况。

重复的原因:
@Transactional 注解和 synchronized 同时作用在一个方法上导致的。

因为Transactional 实现事务的原理是通过动态代理来实现的,会自动帮我们生成一个代理类,而在代理类上我们并没有添加synchronized ,导致代理类不是线程安全的。所以就会出现重复的流水号。

解决办法:
Transactional 和 synchronized 不要同时作用在一个方法上即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值