专栏名称: java那些事
分享java开发中常用的技术,分享软件开发中各种新技术的应用方法。每天推送java技术相关或者互联网相关文章。关注“java那些事”,让自己做一个潮流的java技术人!《java程序员由笨鸟到菜鸟》系列文章火热更新中。
目录
相关文章推荐
51好读  ›  专栏  ›  java那些事

Synchronized锁在Spring事务管理下,为啥还线程不安全?

java那些事  · 公众号  · Java  · 2019-03-20 16:00

正文

请到「今天看啥」查看全文


)

既然Java层面上找不到原因,那分析一下数据库层面的吧(因为方法内操作的是数据库)。在 increaseMoney() 方法前加了 @Transcational 注解,说明这个方法是带有 事务 的。事务能保证同组的SQL要么同时成功,要么同时失败。讲道理,如果没有报错的话,应该每个线程都对money值进行 +1 。从理论上来说,结果应该是1000的才对。

(参考我之前写过的Spring事务: 一文带你看懂Spring事务! )

根据上面的分析,我怀疑是 提问者没测试好 (hhhh,逃),于是我也跑去测试了一下,发现是以提问者的方式来使用 是真的有问题

首先贴一下我的测试代码:


@RestController
public class EmployeeController {

@Autowired
private EmployeeService employeeService;

@RequestMapping ( "/add" )
public void addEmployee () {
for ( int i = 0 ; i 1000
; i++) {
new Thread(() -> employeeService.addEmployee()).start();
}
}


}

@Service
public class EmployeeService {

@Autowired
private EmployeeRepository employeeRepository;


@Transactional
public synchronized void addEmployee () {

// 查出ID为8的记录,然后每次将年龄增加一
Employee employee = employeeRepository.getOne( 8 );
System.out.println(employee);
Integer age = employee.getAge();
employee.setAge(age + 1 );

employeeRepository.save(employee);
}

}


简单地打印了每次拿到的employee值,并且拿到了SQL执行的顺序,如下(贴出小部分):


SQL执行的顺序






请到「今天看啥」查看全文