有个问题,一个spring容器管理项目(service是单例),一个方法会被并发访问,方法为同步方法且用@Transcation注解,数据库隔离机制为可重复读,业务是这样的,用户交易后本地会产生一条交易流水记录,status为0, 然后调用第三方支付,第三方支付会同步异步回调本地这个方法两次, 这个方法内部先判断status是不是为0 ,然后账户增加10元, 那假如同步异步同时回调,那会不会出现该用户账户增加两次金额情况@Transcationpublic synchronized void callback() {查询交易流水记录 statusif(status == 0) {用户帐号 增加10元交易流水记录 status 设为1} else {不作为}}
3 回答
慕神8447489
TA贡献1780条经验 获得超1个赞
在单个JVM的情况下,是没有问题的,但是在集群的环境下有问题,因为Sychronized关键字实际上是JVM级别的,多个JVM不起作用。
建议题主采用的方式:
1)采用悲观锁的方式,select的同时做LOCK(select XXXX for update),效率较低;
2)直接update 加上status=0作为条件:
int num= update ${yourTable} set status=1 where ${yourCondition} and status = 0;
if(num == 0 ) {//update失败处理};
推荐采用第二种方式。
繁星coding
TA贡献1797条经验 获得超4个赞
你这个方法是synchronized,就算是并发,一个进程访问完这个方法,别的进程才能够继续访问。在第一次访问的时候把status设置成1,后面的访问就不会进
if(status == 0) {
用户帐号 增加10元
交易流水记录 status 设为1
}这个判断了,所以不会重复增加。
- 3 回答
- 0 关注
- 142 浏览
添加回答
举报
0/150
提交
取消