当前位置: 首页 > wzjs >正文

网站路径问题芜湖龙湖建设工程有限公司网站

网站路径问题,芜湖龙湖建设工程有限公司网站,iis 网站打不开 建设中,网站建设课设心得体会Spring Boot高并发 锁的使用方法 在高并发场景中(比如电商秒杀、抢票系统、转账交易),多个线程/用户会同时操作同一共享资源(如库存、账户余额、订单号)。如果不做控制,会导致数据错误(如库存超…

Spring Boot高并发 锁的使用方法


在高并发场景中(比如电商秒杀、抢票系统、转账交易),多个线程/用户会同时操作同一共享资源(如库存、账户余额、订单号)。如果不做控制,会导致数据错误(如库存超卖、余额负数)、业务逻辑混乱(如重复下单)。锁(Lock)是解决这类问题的核心工具之一。

一、概述:为什么高并发下需要锁?

1. 高并发的“数据竞争”问题

当多个线程同时修改同一个共享资源时(如数据库的库存字段、内存中的缓存值),如果没有控制,会出现“数据不一致”。例如:

  • 电商场景:商品库存剩余10件,用户A和用户B同时下单,两个线程同时读取到库存为10,都扣减1后写回9,最终库存变成9(实际应卖出2件,库存应为8)。
  • 转账场景:用户账户余额100元,同时发起两笔50元转账,两个线程都读到余额100,都扣减50后写回50,最终余额变成50(实际应扣减100,余额0)。
2. 锁的核心作用

锁是一种“互斥机制”,保证同一时刻只有一个线程能操作共享资源,避免数据竞争。类比现实中的“公共卫生间”:锁门后,其他人必须等待,直到当前用户释放锁(开门)。

二、锁的类型与适用场景

在Spring Boot中,常用的锁分为3类,需根据业务场景选择:

锁类型实现方式适用场景优点缺点
JVM内置锁synchronized关键字单体应用(单进程)的小范围并发代码简单,JVM自动管理锁无法跨进程(分布式场景无效)
JUC显式锁ReentrantLock(Lock接口)单体应用需要灵活控制锁(如超时、可中断)支持超时、可中断、公平锁需要手动释放锁(否则死锁)
分布式锁Redis(Redisson)、ZooKeeper分布式系统(多进程/多服务器)的并发跨进程协调,全局唯一依赖外部组件(如Redis),有性能开销

三、锁的具体使用与代码实现

场景说明:模拟“电商库存扣减”

需求:用户下单时扣减商品库存,要求高并发下库存不能超卖(库存≥0)。
假设商品ID为1001,初始库存10件。

1. JVM内置锁:synchronized

适用于单体应用(只有1个Spring Boot实例),代码简单,JVM自动加锁/释放。

@Service
public class StockService {// 模拟数据库中的库存(实际开发中用数据库或缓存)private int stock = 10;// 下单扣减库存(synchronized保证同一时刻只有1个线程执行)public synchronized boolean deductStock(int productId, int count) {// 检查库存是否足够if (stock < count) {return false; // 库存不足}// 模拟业务耗时(如查询数据库、记录日志)try {Thread.sleep(100);} catch (InterruptedException e) {Thread.currentThread().interrupt();}// 扣减库存stock -= count;System.out.println("扣减成功,剩余库存:" + stock);return true;}
}
关键说明
  • synchronized修饰方法时,锁的是当前对象(this);若修饰静态方法,锁的是类(StockService.class)。
  • 缺点:无法跨进程(如果部署多个Spring Boot实例,每个实例的stock是独立的,锁无效)。
2. JUC显式锁:ReentrantLock

适用于单体应用,但需要更灵活的锁控制(如设置超时、可中断)。

@Service
public class StockService {private int stock = 10;// 显式锁(可重入锁,支持公平/非公平)private final ReentrantLock lock = new ReentrantLock();public boolean deductStock(int productId, int count) {// 尝试加锁(最多等待2秒,避免死锁)try {if (lock.tryLock(2, TimeUnit.SECONDS)) {if (stock >= count) {Thread.sleep(100); // 模拟业务耗时stock -= count;System.out.println("扣减成功,剩余库存:" + stock);return true;} else {System.out.println("库存不足");return false;}} else {System.out.println("获取锁超时");return false;}} catch (InterruptedException e) {Thread.currentThread().interrupt();return false;} finally {// 必须在finally中释放锁(避免异常导致锁未释放)lock.unlock();}}
}
关键说明
  • tryLock(timeout, unit):尝试加锁,超时未获取则放弃(避免线程无限等待)。
  • finally中释放锁:必须手动释放,否则其他线程永远无法获取锁(死锁)。
  • 优点:比synchronized灵活(支持超时、可中断),适合复杂业务逻辑。
3. 分布式锁:Redisson(基于Redis)

适用于分布式系统(多个Spring Boot实例部署),解决跨进程的并发问题。

@Service
public class StockService {@Autowiredprivate RedissonClient redissonClient;// 模拟数据库库存(实际用数据库或缓存,如Redis存储库存)private int stock = 10;public boolean deductStock(int productId, int count) {// 定义锁的名称(按商品ID隔离,不同商品用不同锁)String lockKey = "lock:product:" + productId;RLock lock = redissonClient.getLock(lockKey);try {// 加锁(自动续期,防止业务耗时过长锁过期)// waitTime: 等待锁的最大时间(5秒)// leaseTime: 锁自动释放时间(30秒,防止死锁)boolean locked = lock.tryLock(5, 30, TimeUnit.SECONDS);if (!locked) {System.out.println("获取锁失败,稍后再试");return false;}// 检查并扣减库存if (stock >= count) {Thread.sleep(100); // 模拟业务耗时stock -= count;System.out.println("扣减成功,剩余库存:" + stock);return true;} else {System.out.println("库存不足");return false;}} catch (InterruptedException e) {Thread.currentThread().interrupt();return false;} finally {// 释放锁(只有自己加的锁才能释放)if (lock.isHeldByCurrentThread()) {lock.unlock();}}}
}
关键说明
  • 锁名称:用lock:product:1001隔离不同商品,避免不同商品的库存操作互相阻塞。
  • 自动续期:Redisson默认会为锁“续期”(每10秒续30秒),防止业务逻辑未执行完锁就过期(比如扣库存需要20秒,锁30秒过期,续期避免提前释放)。
  • 分布式场景有效性:多个Spring Boot实例通过Redis的lockKey协调,同一时刻只有1个实例能获取锁,避免跨进程的库存超卖。

四、实际业务举例:电商秒杀场景

场景描述

某商品开启秒杀(库存100件),1000个用户同时点击“立即购买”,需要保证:

  • 只有前100个用户能成功购买(库存不超卖)。
  • 后续用户提示“已售罄”。
解决方案(分布式锁)
  1. 用户点击下单时,先通过Redisson获取该商品的分布式锁(lock:seckill:productId)。
  2. 获得锁的线程检查库存是否足够(stock > 0)。
  3. 库存足够则扣减库存,生成订单;否则返回“已售罄”。
  4. 释放锁,让其他线程继续竞争。
关键点
  • 锁粒度:按商品ID加锁(如lock:seckill:1001),不同商品的秒杀互不影响,提升并发效率。
  • 防死锁:设置锁的自动释放时间(如30秒),即使业务异常未释放锁,锁也会自动过期。
  • 性能优化:库存可存储在Redis中(GET/SET操作比数据库快),减少数据库压力。

五、总结

1. 锁的选择原则
  • 单体应用:优先用synchronized(简单)或ReentrantLock(需要灵活控制)。
  • 分布式系统:必须用分布式锁(如Redisson),避免跨进程数据竞争。
2. 注意事项
  • 锁粒度:尽量缩小锁的范围(只锁共享资源的操作代码),避免“锁整个方法”降低性能。
  • 防死锁:设置锁的超时时间(如tryLock(5, 30, TimeUnit.SECONDS)),避免线程无限等待。
  • 性能权衡:锁会降低并发吞吐量(同一时刻只有1个线程操作),需结合业务场景(如秒杀允许少量延迟)。
3. 扩展思考
  • 无锁方案:对于简单计数(如访问量),可用AtomicInteger(基于CAS无锁操作),但无法解决复杂业务逻辑(如库存扣减+订单生成)。
  • 读写锁:读多写少场景(如商品详情页缓存),可用ReentrantReadWriteLock(允许多个读锁并发,写锁互斥)。
http://www.dtcms.com/wzjs/562248.html

相关文章:

  • 卡盟网站怎么做图片福州市建设局内部网站
  • 站长之家备案查询网站建设课程设计
  • 网站开发一般要多少钱做网站客户怎么找
  • 企业网站的制作哪家好怎么样建立一个网站
  • 建设投资公司网站网站正在建设中色无夜
  • 物流企业网站建设与管理规划书阿里云网站空间做商城流程
  • 广州定制型网站建设网站建设模板套用
  • 怎么自己做企业网站广告设计合同模板
  • 去除WordPress注册功能平台关键词排名优化
  • 网站建设企业模板深圳商业网站建设模板
  • 分类网站怎么做项目vi企业形象设计公司
  • 廊坊哪家公司做网站网站首页建设建议
  • 做网站的需要哪些职位商城类网站建设数据库
  • 怎么在欧美做网站推广wordpress加统计代码
  • 设计在线设计网站大型网站 jquery
  • 网站后台不能上传晨星wordpress 主题
  • 有一个网站怎么做cpc自助网站建设技术支持
  • 遵义住房和城乡建设局网站网站源码资源
  • 广州网站推广¥做下拉去118cr千套模板快速自助建站
  • 北京建设网站兼职普工搜索引擎关键词怎么选
  • 周口网站建设那个网站做拍手比较好
  • 网站开发项目管理步骤seo专员简历
  • 福州做网站多少钱深圳市水榭花都房地产公司
  • 怎么在子域名建立一个不同的网站wordpress 取消边栏
  • 做网站有什么软件吗火车头wordpress发布模块4.9
  • 湖州高端网站建设重庆1000元网站建设
  • 常州市网站建设公司跨境电商平台介绍
  • 大气科技类企业公司网站源码丹阳网站
  • 上海网站建设案例新型网站设计
  • 广州正规网站制作公司哪些网站可以做go注释