You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
|
|
# 一、在service层事务中使用锁(失效)
|
|
|
|
|
```java
|
|
|
|
|
//伪代码
|
|
|
|
|
@Transactional
|
|
|
|
|
public sync Object test(){
|
|
|
|
|
xxx()
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
上述代码执行过程:
|
|
|
|
|
1. spring AOP 生成代理对象,开启事务
|
|
|
|
|
2. 线程1获得锁
|
|
|
|
|
3. 线程1执行xxx方法
|
|
|
|
|
4. 线程1释放锁
|
|
|
|
|
5. 事务提交
|
|
|
|
|
|
|
|
|
|
问题点:线程1释放锁之后,事务提交之前。由线程2获取锁执行,此时线程2查到的数据是脏数据,因此出现脏写。
|
|
|
|
|
|
|
|
|
|
## 解决:
|
|
|
|
|
### 1. 将加锁过程上移至controller层
|
|
|
|
|
原理是将事务包在锁内
|
|
|
|
|
```java
|
|
|
|
|
private final Lock lock = new ReentrantLock(false);
|
|
|
|
|
|
|
|
|
|
public ServiceResult<?> save(@RequestBody CreditRecordsParam params) {
|
|
|
|
|
try {
|
|
|
|
|
if (lock.tryLock(5, TimeUnit.SECONDS)) {
|
|
|
|
|
return creditRecordsService.save(params);
|
|
|
|
|
} else {
|
|
|
|
|
return ServiceResult.fail("锁获取失败,请重新提交");
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
return ServiceResult.fail(e.getMessage());
|
|
|
|
|
} finally {
|
|
|
|
|
lock.unlock();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 2. 在service层新建无事务方法
|
|
|
|
|
原理和1相同,使用无事务方法加锁后调用有事务方法。
|