您的位置:首页 > 编程语言 > Java开发

Spring @transactional注解和synchronized同步锁同时使用不能同步的问题

2018-01-20 00:00 1636 查看
摘要: 目前在做的系统中有一个获取流水号的功能,要求每次请求获取到的流水号唯一。为控制并发问题,想过在用Synchronized method(){}或者method(){ Synchronized(this){ } }来控制,两个同样的记录去做并发测试,同步方法或者代码块并没有起作用。Synchronized加在@Transactional事务注解的方法时,同步并不起作用,可以新建不带用事务注解的同步方法,然后再调用method。

如果在service层的方法上同时使用事务和同步锁无法保证数据同步

@Service
public class Service{
@Transactional(readOnly = false)
public void synchronized update() {
............
}
}

*上面这个例子无法保证数据的一致性

由于spring的AOP的特性,会在update方法之前开启事务,之后再加锁,当锁住的代码执行完成后,在提交事务。

因此synchronized代码块执行是在事务之内执行的,可以推断在代码块执行完时,事务还未提交,因此其它线程进入synchronized代码块后,读取的数据库数据不是最新的。

为了解决上面的并发同步问题,可以通过synchronized方法调用update()方法,在还没有开事务之前就加同步锁,那么就可以保证线程同步。

1、原实现同步方法

同步方法或者同步方法块都不能达到同步的作用。

@Service
public class Service{

@Transactional(readOnly = false,rollbackFor = SQLException.class)
public synchronized void synMethodOne() throws SQLException{
............
}
}

@Service
public class Service{

@Transactional(readOnly = false,rollbackFor = SQLException.class)
public void synMethodTwo() throws SQLException{
synchronized(this){
............
}
}
}

2、修改后的方法

@Service
public class noTransService {

@Autowired
SynchronizedService synchronizedService;

public synchronized void synMethod() throws SQLException{
synchronizedService.synMethodTwo();
}

}

@Service
public class SynchronizedService{

@Transactional(readOnly = false,rollbackFor = SQLException.class)
public void synMethodTwo() throws SQLException{
............
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息