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

怎么做地区网站精准客源引流平台

怎么做地区网站,精准客源引流平台,网络营销策略分析案例,建站宝盒可以做视频聊天交友网站吗什么是死锁? 场景:图书馆有两个相邻的储物柜(柜子A和柜子B),小明和小红需要同时使用这两个柜子才能完成借书流程。 互斥资源 每个柜子只有一把钥匙,且一次只能被一人使用(资源不可共享&#x…

请添加图片描述

什么是死锁?

场景:图书馆有两个相邻的储物柜(柜子A和柜子B),小明和小红需要同时使用这两个柜子才能完成借书流程。

  1. 互斥资源
    每个柜子只有一把钥匙,且一次只能被一人使用(资源不可共享)。
  2. 持有并等待
    • 小明拿到了柜子A的钥匙,但他说:“我要等小红用完柜子B的钥匙,才能继续操作。”
    • 小红拿到了柜子B的钥匙,但她说:“我要等小明用完柜子A的钥匙,才能继续操作。”
  1. 僵局形成
    两人都死死攥着已有的钥匙,同时等待对方手里的另一把钥匙。结果两人卡在原地,谁也无法完成借书流程。

死锁的定义:线程A获取到资源1,需要再次获取到资源2被释放以获取到该资源,此时线程B获取到了资源2,等待获取资源1,两线程进入了互相等待的状态形成死锁。

请添加图片描述

业务中的死锁

让我们以电商系统中的「购物车库存锁定」场景为例,具体分析死锁的触发机制:当用户A尝试同时锁定商品X和Y的库存,而用户B以相反顺序(先锁Y再锁X)发起操作时,这两个并发请求可能因资源竞争进入相互等待状态——此时系统既无法完成库存扣减,也无法释放已占用的资源,形成典型的死锁僵局。

MockData类初始化了商品的库存,使用ConcurrentHashp模拟购物车和商品库存信息,并提供了添加至购物车、清空购物车、扣减库存等方法。

public class MockData {// 模拟购物车:用户ID -> 商品列表 + 总价public static final ConcurrentHashMap<Long, Cart> Carts = new ConcurrentHashMap<>();// 模拟库存:商品ID -> 库存数量public static final ConcurrentHashMap<Long, AtomicInteger> Inventory = new ConcurrentHashMap<>();static {// 初始化库存(商品1和2各有1件)Inventory.put(1L, new AtomicInteger(1));Inventory.put(2L, new AtomicInteger(1));}// 添加商品到购物车public static void addToCart(Long userId, Long productId, int quantity) {Carts.computeIfAbsent(userId, k -> new Cart()).addProduct(productId, quantity);}// 清空购物车public static void clearCart(Long userId) {Carts.remove(userId);}// 获取库存数量public static int getStock(Long productId) {return Inventory.getOrDefault(productId, new AtomicInteger(0)).get();}// 扣减库存(原子操作)public static boolean decreaseStock(Long productId, int quantity) {return Inventory.getOrDefault(productId, new AtomicInteger(0)).compareAndSet(getStock(productId), getStock(productId) - quantity);}// 购物车类static class Cart {private final ConcurrentHashMap<Long, Integer> items = new ConcurrentHashMap<>();@Getterprivate int totalPrice = 0;/*** 购物车添加商品* @param productId 商品id* @param quantity 数量*/public void addProduct(Long productId, int quantity) {items.put(productId, items.getOrDefault(productId, 0) + quantity);totalPrice += quantity;}public void removeProduct(Long productId) {items.remove(productId);totalPrice -= items.getOrDefault(productId, 0);}}
}

以下代码模拟库存不足造成死锁的场景:

@Slf4j
@Service
@EnableAsync
public class OrderService {// 死锁场景(模拟库存不足)public void createOrderDeadLock(Long userId, Long productId) {log.info("用户:{},开始下单商品:{}", userId, productId);// 模拟购物车添加商品cartLock.lock();try {// 步骤2:检查库存(此时可能有其他线程扣减)if (MockData.getStock(productId) < 1) {log.error("用户:{} 库存不足,放弃订单", userId);return;}// 模拟长时间业务操作(人为制造时间差)try {Thread.sleep(5000);} catch (Exception e) {log.error("异常", e);}// 步骤3:扣减库存(实际业务场景需要原子操作)if (!MockData.decreaseStock(productId, 1)) {log.error("用户:{} 库存已被抢光,放弃订单", userId);return;}log.info("用户 {},下单成功", userId);MockData.clearCart(userId);} catch (Exception e) {log.error("下单失败", e);} finally {cartLock.unlock();}}
}

在Controller层调用该方法,同时进行场景分析:

死锁场景分析:

  • 核心逻辑:两个用户同时抢购同一商品,库存仅剩1件。
  • 死锁原因
    1. 线程1持有购物车锁,等待库存锁。
    2. 线程2持有购物车锁,等待库存锁。
    3. 双方互相等待对方释放锁,形成循环等待。
    @GetMapping("/wrong/cert/lock")public void wrongCertLock() throws InterruptedException {ExecutorService executor = Executors.newFixedThreadPool(2);// 用户A尝试购买商品1(库存1)executor.submit(() -> orderService.createOrderLockBySequence(1L, 1L));// 用户B尝试购买商品1(库存已不足)executor.submit(() -> orderService.createOrderLockBySequence(2L, 1L));// 等待观察结果(死锁表现为长时间无输出)executor.shutdown();executor.awaitTermination(20, TimeUnit.SECONDS);}
}

使用工具调用该接口,并查看接口的输出结果,接口响应时间5.08秒:

请添加图片描述

在下单时使用购物车的全局锁certLock时,存在两个问题:

一.单锁阻塞堆积(隐性"假死锁")

当使用全局锁 cartLock 时,所有下单请求必须串行执行。在高并发场景下:

  1. 第一个线程获得锁后执行5秒休眠
  2. 后续所有线程在 cartLock.lock()处排队阻塞
  3. 线程堆积导致系统吞吐量骤降,最终表现类似"死锁"

数据示例:

  • 假设QPS=100,5秒内会堆积500个等待线程
  • 实际业务处理能力被压缩到0.2 TPS(每秒处理0.2个请求)

使用Arthasthread -b命令分析服务存在线程“死锁”的情况和线程阻塞情况,同时Arthas支持查看阻塞位置的源码。

请添加图片描述

使用jad --jad --source-only命令查看源码,如例子中展示第40行附近存在线程阻塞的问题,我们可以通过反编译查看源码:

jad --source-only com.codetree.business_error.chapter.chapter02.shop.OrderService createOrderDeadLock

请添加图片描述

二、锁粒度错位导致的竞态条件
隐患根源:
// 非原子操作
if (MockData.getStock(productId) < 1) {return;
}
// 非原子操作
MockData.decreaseStock(productId, 1)    

即使有全局锁保护:

  1. 库存检查与扣减分离:其他系统(如支付系统)可能同时修改库存
  2. 超卖风险:检查时库存充足,但扣减时已被其他通道(API/后台)修改

如何避免死锁?

避免死锁一般有两种方案:

方案实现方式优点缺点
一次性获取资源使用全局锁(globalLock简单粗暴,彻底避免死锁并发性能差,所有请求串行执行
按顺序获取资源固定锁顺序(先购物车 → 再库存)兼顾并发性能,适用于复杂业务需全局统一锁顺序策略
方案一、一次性获取所有资源

一次性获取所有资源可以视为将多个非原子性操作封装成一个大的原子性操作,强制实现线程“串行化”访问,该方案能够彻底消除持有并等待条件,同时保证临界区操作的原子一致性。

    public void createOrderLockAllResource(Long userId, Long productId) {log.info("优化:一次性获取所有的资源,用户:{},开始下单商品:{}", userId, productId);// 模拟购物车添加商品globalLock.lock();try {// 步骤2:检查库存(此时可能有其他线程扣减)if (MockData.getStock(productId) < 1) {log.error("用户:{} 库存不足,放弃订单", userId);return;}// 模拟长时间业务操作(人为制造时间差)try {Thread.sleep(10000);} catch (Exception e) {log.error("异常", e);}// 步骤3:扣减库存(实际业务场景需要原子操作)if (!MockData.decreaseStock(productId, 1)) {log.error("用户:{} 库存已被抢光,放弃订单", userId);return;}log.info("用户 {},下单成功", userId);MockData.clearCart(userId);} catch (Exception e) {log.error("下单失败", e);} finally {globalLock.unlock();}}

未出现阻塞问题,串行化执行成功,接口响应10.10秒。

请添加图片描述

方案二、按顺序获取资源

顺序化获取资源可以有效规避死锁产生的必要条件(之一)——循环等待条件,同时消除进程间非原子操作的竞争冲突,从而避免竞态条件的发生。

    public void createOrderLockBySequence(Long userId, Long productId) {log.info("优化:按顺序获取锁,用户:{},开始下单商品:{}", userId, productId);// 模拟购物车添加商品cartLock.lock();try {// 步骤2:获取库存锁inventoryLock.lock();try {// 快速失败if (MockData.getStock(productId) < 1) {System.out.println("用户 " + userId + " 库存不足,方案二无效");return;}// 执行所有操作MockData.addToCart(userId, productId, 1);MockData.decreaseStock(productId, 1);System.out.println("用户 " + userId + " 方案二下单成功!");MockData.clearCart(userId);} catch (Exception e) {log.error("异常", e);throw new RuntimeException(e);} finally {inventoryLock.unlock();}} catch (Exception e) {log.error("下单失败", e);} finally {cartLock.unlock();}}

请添加图片描述

总结

在并发系统的设计与优化中,死锁预防始终是确保系统稳定性的核心命题,我介绍的两种死锁的处理方式:

  1. "一刀切"的原子化方案
    通过全局锁强制串行化操作,牺牲了并发性能,以最简单的方式彻底消除死锁风险。这种"粗暴但可靠"的设计思路,特别适合对数据一致性要求极高、容错成本较大的业务场景,保证了基本的安全性。
  2. 精细化控制的顺序化策略
    访问资源顺序化,投机取巧的利用了业务场景优势,方案适合于对接口响应时间敏感的业务场景(下单抢购)。

实践启示录:

  • 没有银弹的解决方案:两种方案各有利弊,需根据业务特性进行取舍。高频小事务场景宜用原子化方案,长流程多步骤业务则更适合顺序化控制。
  • 死锁预防≠完全消除:即使采取最优策略,仍需通过监控(如JVM线程Dump分析)、日志埋点(死锁检测)、压力测试等手段持续验证系统稳定性。

优秀的设计永远是在理论模型与实际需求之间寻找精妙的平衡点。希望本文的分析能为你提供一些新的思路。

http://www.dtcms.com/wzjs/60209.html

相关文章:

  • 网站建设费用设计百度产品优化排名软件
  • 做网站多少钱赚钱吗企业网络营销策划案
  • 如何在电影网站中做淘客举出最新的网络营销的案例
  • 怎么重新安装我的wordpress温州seo顾问
  • 湖北建站中心网络推广公司排名
  • 网站收录在下降公司网站制作费用
  • 济南专业做网站的公司友博国际个人中心登录
  • 鲜花网站建设规划百度下载app下载安装到手机
  • 多用户网站友情链接网址
  • 中国网络科技公司排名seo优化公司信
  • 做网站优化价格引擎网站推广法
  • 百度收录较好的网站什么推广平台好
  • 米问外贸论坛seo是什么牌子
  • 宁波学校网站建设整站优化 快速排名
  • 广州企业网站建设费用百度网站是什么
  • 手机怎么制作网站佛山网站建设工作
  • 如何申请免费的网站空间在线crm软件
  • 做网站有哪些软件合作seo公司
  • 公司网站制作银川使用网站模板快速建站
  • 有没有网站做设计可以赚钱品牌宣传活动策划方案
  • 网站二次开发是什么网址生成短链接
  • 罗湖网站建设费用app地推接单平台
  • 山东网站建设优化可以商用的电视app永久软件
  • 辽宁网站建设培训班网络整合营销4i原则
  • 网站建设服务合同纠纷抖音seo关键词优化怎么做
  • 黄冈商城网站制作哪家好网络技术培训
  • 门户网站建设要求网站建设网站推广
  • java网站建设公司 北京seo计费怎么刷关键词的
  • 昆明淘宝网站建设网站推广主要是做什么
  • 做第三方seo优化网站安卓系统优化大师