需求
业务id需要自定义规则 + 自增生成,不允许重复。
问题
Service方法添加了@Synchronized,日志中打印的顺序正常,锁是生效的,查看日志发现在上一条数据插入后,再次查询数据库时,没有查询到这条信息,导致生成的id依然会有重复现象。
解决方法
将锁从service方法更换到controller层,问题解决。
同理,添加一个方法,将锁加在该方法上,在该方法内部调用原方法也可以解决。
原因分析
原因很简单,但容易在做代码修改时遗漏。
该Service方法上添加了@Transactional注解,开启事务,锁也是添加在该方法上,导致锁的有效范围在事务的范围内,在事务还未提交时,新的线程已经拿到锁并开始查询,因此查不到刚刚添加的数据。即:锁应放在事务外围。
为什么@Transactional会导致该锁失效?因为@Transactional是利用AOP实现的,看起来该方法结束后就立即提交了事务,实际上并没有,而该方法结束之后会立即释放锁,新的线程已经拿到锁并开始执行方法,而提交事务的操作还在执行中。