- 问题
最近做一个好友砍价的功能,好友砍价时需要进行同步处理,避免并发时砍价金额出现异常。原来代码是在service中使用synchronized进行并发控制,代码如下
@Override
@Transactional(rollbackFor = Exception.class)
public BigDecimal help(BargainHistory history) {
String intern = String.valueOf(history.getId()).intern();
synchronized (intern) {
// 砍价逻辑代码
}
}
本来以为没什么问题,但是在测试的过程中却发现还是出现了并发,最后发现是因为加了@Transactional
的原因,由于添加了事务控制,数据库操作不会在每一个线程执行完成后都立即commit,导致出现脏数据。
- 解决方法
将synchronized同步处理放在controller层即可解决,修改后controller层代码如下
@PostMapping("help")
public Response<BigDecimal> help(@RequestBody BargainHistory history){
// 加锁
Object intern = String.valueOf(history.getId()).intern();
synchronized (intern) {
logger.info("------------controller intern------------:" + System.identityHashCode(intern));
return Response.rspData(this.bargainService.help(history));
}
}
service层代码去掉同步代码,保留@Transactional即可
@Override
@Transactional(rollbackFor = Exception.class)
public BigDecimal help(BargainHistory history) {
// 砍价逻辑代码
}