Synchronized
线程同步锁,被synchronized修饰的方法、代码块.能够保证同时只有一个线程访问该代码.
@Transactional
介绍
Spring提供的一种事务提交/回滚的方法.可以修饰在类、接口以及方法上面.
错误的使用方式
@Override
@Transactional(rollbackFor = Exception.class)
public synchronized Result testTransactional() {
Ebook ebook = getById(5);
Integer docCount = ebook.getDocCount();
if (docCount > 0) {
DocInfo docInfo = new DocInfo();
docInfo.setTest("1");
docInfoService.save(docInfo);
update(Wrappers.<Ebook>lambdaUpdate().set(Ebook::getDocCount, ebook.getDocCount() - 1).eq(Ebook::getId, 5));
return Result.ok();
}
return Result.error();
}
错误原因: @Transactional是通过AOP的方式实现事务提交/回滚.所以@Transactional与synchronized的执行顺序为.AOP开启事务-> synchronized加锁-> 释放锁-> 提交/回滚事务.在释放锁和提交/回滚事务之间可能会有其它线程进入造成线程不安全.
正确使用方式
** 先加锁再开启事务 **
@Override
public synchronized Result testTransactional() {
return getResult();
}
@Transactional(rollbackFor = Exception.class)
public Result getResult() {
Ebook ebook = getById(5);
Integer docCount = ebook.getDocCount();
if (docCount > 0) {
DocInfo docInfo = new DocInfo();
docInfo.setTest("1");
docInfoService.save(docInfo);
update(Wrappers.<Ebook>lambdaUpdate().set(Ebook::getDocCount, ebook.getDocCount() - 1).eq(Ebook::getId, 5));
return Result.ok();
}
return Result.error();
}