用JVM本地锁解决并发问题 并分析导致锁失效的原因
使用场景
在电商项目中,比如秒杀、抢购等活动中,经常会出现超卖现象,库中明明有1000个库存,可是被下单了1100个,本期用比较简单的方法来解决这个问题。
解决方法
一、用JVM锁synchronized解决该问题
例如下面代码中我在方法上加入本地锁synchronized也可以解决这个问题
public synchronized void deduct(){
Stock stock = stockMapper.selectOne(new LambdaQueryWrapper<Stock>().eq(Stock::getProduct_code, "10001"));
}
}
二、使用ReentrantLock解决该问题
private ReentrantLock lock = new ReentrantLock();
public void deduct(){
lock.lock();
try {
Stock stock = stockMapper.selectOne(new LambdaQueryWrapper<Stock>().eq(Stock::getProduct_code, "10001"));
} finally {
lock.unlock();
}
}
分析本多锁失效原因
一、多例模式
一般service是单例的,如果将service改为多例时,就会出现并发问题
修改为多例代码如下 添加Scope注解
@Service
@Scope(value = "prototype",proxyMode = ScopedProxyMode.TARGET_CLASS)
public class StockService
二、事务
一般在service中我们会直接加上@Transactional 注解来给这个方法加上事务
然而这个注解也会导致我们的锁失效
@Transactional
public synchronized void deduct(){
三、集群部署
当我们的项目不是单机应用时,也就是集群部署时,这时就会导致JVM锁失效
可以使用本地nginx验证
以上可以通过jmeter进行测试
jmeter工具已经上传至资源