【发布时间】:2017-05-08 23:14:03
【问题描述】:
在多线程下,我不断从存储库中获取旧结果。
@Transactional(isolation = Isolation.REPEATABLE_READ)
public void updateScore(int score, Long userId) {
logger.info(RegularLock.getInstance().getLock().toString());
synchronized (RegularLock.getInstance().getLock()) {
Customer customer = customerDao.findOne(userId);
System.out.println("start:": customer.getScore());
customer.setScore(customer.getScore().subtract(score));
customerDao.saveAndFlush(customer);
}
}
CustomerDao 看起来像
@Transactional
public T saveAndFlush(T model, Long id) {
T res = repository.saveAndFlush(model);
EntityManager manager = jpaContext.getEntityManagerByManagedType(model.getClass());
manager.refresh(manager.find(model.getClass(), id));
return res;
}
saveAndFlush() from JpaRepository 用于立即保存更改并锁定整个代码。但我仍然不断得到旧的结果。
java.util.concurrent.locks.ReentrantLock@10a9598d[Unlocked]
start:710
java.util.concurrent.locks.ReentrantLock@10a9598d[Unlocked]
start:710
我正在使用带有 spring data jpa 的 springboot。
我把所有代码放在一个测试控制器中,问题依旧
@RestController
@RequestMapping(value = "/test", produces = "application/json")
public class TestController {
private static Long testId;
private final CustomerBalanceRepository repository;
@Autowired
public TestController(CustomerBalanceRepository repository) {
this.repository = repository;
}
@PostConstruct
public void init() {
// CustomerBalance customer = new CustomerBalance();
// repository.save(customer);
// testId = customer.getId();
}
@SystemControllerLog(description = "updateScore")
@RequestMapping(method = RequestMethod.GET)
@Transactional(isolation = Isolation.REPEATABLE_READ)
public CustomerBalance updateScore() {
CustomerBalance customerBalance = repository.findOne(70L);
System.out.println("start:" + customerBalance.getInvestFreezen());
customerBalance.setInvestFreezen(customerBalance.getInvestFreezen().subtract(new BigDecimal(5)));
saveAndFlush(customerBalance);
System.out.println("end:" + customerBalance.getInvestFreezen());
return customerBalance;
}
@Transactional
public CustomerBalance saveAndFlush(CustomerBalance customerBalance) {
return repository.saveAndFlush(customerBalance);
}
}
结果是
start:-110.00
end:-115.00
start:-110.00
end:-115.00
start:-115.00
end:-120.00
start:-120.00
end:-125.00
start:-125.00
end:-130.00
start:-130.00
end:-135.00
start:-130.00
end:-135.00
start:-135.00
end:-140.00
start:-140.00
end:-145.00
start:-145.00
end:-150.00
【问题讨论】:
-
附带问题:为什么要使用 ReentrentLock 作为同步块的监视器……为什么还要有同步块?
-
@JensSchauder 有多种方法可以改变分数。我正试图阻止他们参加比赛
-
1.为什么不直接同步服务/控制器或我们在此处查看的内容。
-
2.如果你有一个正常的 spring 设置,每个线程都有一个 entityManager,所以并发访问应该不是问题,只要你的类中没有状态。
-
另一个问题:你能打印出分数来确定它实际上与零不同吗?
标签: java multithreading spring-boot spring-data-jpa