今天,当我学习使用“可重入锁”时,我遇到了一个问题。在售卖商品业务代码中添加锁。
@Service
public class ServiceOne{
private Lock lock = new ReentrantLock(true);
public Result func(long seckillId, long userId) {
lock.lock();
// Check stock
// sale
// Reduce stock
lock.unlock();
}
}前提是使用MySQL数据库的重读隔离机制。在高并发的情况下,假设有多个线程同时调用该方法。当交易可以在“lock”和“unlock”之间完全打开和提交时,就不会出现超卖问题。
显然,事务必须在“lock”之后启动,所以关键是事务是否必须在“unlock”之前提交。如果它是在“unlock”之后,那么它确实有可能超卖:例如,当线程1完成执行方法,但事务尚未提交时,线程2获得锁并开始执行该方法。在可重复读隔离机制下,线程2无法读取线程1对存储的操作结果,因而超卖。
我希望你能来回答你的问题!感激不尽!
发布于 2021-07-17 19:00:29
是在方法结束之后还是之前提交的事务?
您的方法不仅仅是Spring实际执行的方法。Spring使用代理,因此您可以为您的类和方法创建一个代理。
如前所述,@Transactional是使用方面around实现的,这意味着方法执行之前的一些代码和方法执行后的一些代码也会被执行。
所以如果你写了
@Transactional
public void method1 () {
doSomething1;
doSomething2;
}spring的代理实际上看起来是什么样子
public void method1 () {
/*
Extra code from spring to open a transaction.
/*
doSomething1;
doSomething2;
/*
Extra code from spring to close a transaction.
/*
}简要回答:事务将在您编写的方法的所有语句执行完毕后关闭。
如果没有声明返回任何内容,则将调用提交。
发布于 2021-07-17 15:19:24
@Transactional用于使该操作成为原子操作。表示在方法结束时执行解锁。
https://stackoverflow.com/questions/68417931
复制相似问题