深入解析与解决高并发下的线程池死锁问题

问题背景

在现代互联网应用中,高并发场景是常态,为了高效处理大量用户请求,后端服务通常会采用线程池来管理线程资源。然而,在一个复杂的微服务架构项目中,我们遇到了一个棘手的问题:在业务高峰期,系统频繁出现响应延迟甚至超时的情况,经过初步排查,发现部分服务存在线程池死锁现象,严重影响了系统的稳定性和用户体验。

问题分析

该系统采用Spring Boot框架构建,核心业务模块负责处理用户订单,包括订单创建、支付状态更新以及库存调整等操作。为了提高处理效率,我们为每个处理逻辑配置了独立的线程池。问题主要出现在订单支付成功后的库存减少操作上,具体代码片段如下:

@Service
public class OrderService {@Autowiredprivate StockService stockService;@Async("stockThreadPool")public void deductStockAfterPaymentSuccess(Order order) {stockService.deduct(order.getProductId(), order.getQuantity());// 更新订单状态等后续逻辑...}
}

其中,stockThreadPool 是一个自定义配置的线程池,用于处理库存相关的异步操作,以避免库存操作阻塞主线程。然而,在高并发环境下,该线程池经常达到最大线程数,新来的请求因无法获取线程而被无限期地等待,导致线程池死锁。

排查过程
  1. 监控工具辅助:首先,利用JVisualVM、arthas等工具监控系统线程状态,发现stockThreadPool中的线程大多处于WAITING状态,说明存在线程等待资源释放的情况。
  2. 代码审查:检查StockService.deduct()方法实现,发现内部使用了悲观锁(如synchronized或Lock的lock()方法),在高并发下容易形成锁竞争,导致线程等待时间过长。
  3. 日志分析:通过增加详细的日志记录,观察到在某些时间点,多个线程同时尝试锁定相同的商品库存记录,形成了锁链,进而引发了死锁。
解决方案
  1. 优化锁策略:将悲观锁改为乐观锁。在库存服务中,使用版本号或时间戳进行并发控制,减少直接的线程等待。例如,使用@Version注解结合Spring Data JPA的乐观锁机制。
@Entity
public class Product {@Idprivate Long id;private Integer stock;@Versionprivate Long version;// getters and setters
}
@Service
public class StockService {@Transactionalpublic boolean deduct(Long productId, Integer quantity) {Product product = productRepository.findById(productId).orElseThrow(() -> new ResourceNotFoundException("Product not found"));if (product.getStock() < quantity) return false;int updatedStock = product.getStock() - quantity;product.setStock(updatedStock);try {product = productRepository.save(product);} catch (OptimisticLockException e) {// 处理乐观锁失败,通常重试或记录日志return false;}return true;}
}

线程池配置优化:根据业务负载情况动态调整线程池参数,如核心线程数、最大线程数、队列大小及拒绝策略等,避免固定配置在高并发下成为瓶颈。使用ThreadPoolExecutor自定义配置,并考虑使用ThreadPoolExecutor.CallerRunsPolicy作为拒绝策略,让调用者线程执行任务,避免直接丢弃任务。

@Configuration
public class ThreadPoolConfig {@Bean(name = "optimizedThreadPool")public ThreadPoolTaskExecutor threadPoolTaskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();// 核心线程数,根据CPU核心数和业务需求合理设定executor.setCorePoolSize(4 * Runtime.getRuntime().availableProcessors());// 最大线程数,防止线程数无限制增长导致资源耗尽executor.setMaxPoolSize(executor.getCorePoolSize() * 2);// 队列大小,当核心线程都被占用时,新任务将在队列中等待executor.setQueueCapacity(500);// 拒绝策略,这里采用CallerRunsPolicy,让调用者线程执行任务executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());// 设置线程空闲时间,超过该时间的空闲线程将被终止executor.setKeepAliveSeconds(60);// 线程名前缀,方便日志追踪executor.setThreadNamePrefix("OptimizedThreadPool-");// 初始化线程池executor.initialize();return executor;}
}

在服务类中使用自定义线程池:

@Service
public class OrderService {@Autowired@Qualifier("optimizedThreadPool") // 使用自定义线程池private ThreadPoolTaskExecutor executor;public void deductStockAfterPaymentSuccess(Order order) {executor.execute(() -> {stockService.deduct(order.getProductId(), order.getQuantity());// 更新订单状态等后续逻辑...});}
}

增加超时与重试机制:对于可能引起长时间等待的操作,如数据库操作、远程服务调用等,设置合理的超时时间,并在超时后实施重试逻辑,以减少单次请求对系统资源的占用, 使用Future结合自定义的超时和重试。

@Service
public class OrderService {// ... 其他代码 ...public void deductStockWithRetry(Order order) {int retryCount = 0;final int maxRetries = 3; // 最大重试次数while (retryCount <= maxRetries) {try {Future<Boolean> resultFuture = executor.submit(() -> stockService.deduct(order.getProductId(), order.getQuantity()));// 使用自定义的超时时间,5秒if (resultFuture.get(5, TimeUnit.SECONDS)) {System.out.println("库存扣减成功");break; // 成功则跳出循环} else {throw new RuntimeException("库存不足,扣减失败");}} catch (TimeoutException e) {System.out.println("库存扣减操作超时,准备重试...");} catch (InterruptedException | ExecutionException e) {System.out.println("操作异常,准备重试... " + e.getMessage());}retryCount++;if (retryCount > maxRetries) {System.out.println("重试次数已达上限,操作失败");break;} else {try {Thread.sleep(1000); // 退避策略,重试前等待一秒} catch (InterruptedException ignored) {}}}}
}
成果与思考

经过上述改造,系统在高并发场景下的表现有了显著提升,线程池死锁问题得到有效解决,用户请求响应时间和系统稳定性得到了大幅改善。监控数据显示,线程池利用率更加合理,未再出现请求堆积和长时间等待的情况。

此次经历让我们深刻认识到:

  • 并发控制策略的重要性:合理选择锁策略(乐观锁与悲观锁),能够有效避免死锁和性能瓶颈。
  • 线程池配置的灵活性:动态调整线程池参数,根据实际业务需求和系统负载进行优化,是保障系统稳定的关键。
  • 全面的监控与日志:良好的监控和日志体系是问题定位和系统调优的基石,能够快速定位并解决问题。

总之,面对高并发挑战,开发人员需要综合运用多种技术手段,不断优化和调整,才能确保系统的高效稳定运行。

欢迎扫码关注 微信公众号:JAVA和人工智能
                                                           获取更多免费书籍、资源、优质资料 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/859739.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WSL安装的Ubuntu与docker desktop集成

WSL安装的Ubuntu与docker desktop集成 最近因为项目需要&#xff0c;要在本地利用WSL搭建一个docker和Ubuntu的部署环境。一开始并不知道docker desktop与Ubuntu可以集成使用&#xff0c;所以在Ubuntu上独立安装了docker引擎&#xff0c;但在安装docker-compose的时候出现以下…

MN316 AT模式丨低功耗实测分析

NB-IoT模组的应用场景一般具备低频次、小数据量、上行为主、工作时间短&#xff08;激活态时间短&#xff09;等特点。因此&#xff0c;休眠态的功耗是NB-IoT模组产品综合耗电的重点考量参数之一。中移物联OneMO超低功耗NB-IoT模组MN316&#xff0c;凭借其紧凑的尺寸、极低的休…

天翼云服务器80、443等特殊端口无法访问原因记录

之前阿里云、腾讯云的服务器上&#xff0c;想要用域名访问项目简单配置就好了&#xff0c;这次甲方直接买的翼云的服务器&#xff0c;配置了半天&#xff0c;防火墙端口80、443端口开放了&#xff0c;控制台安全组也添加了&#xff0c;就是不能用域名或IP直接访问&#xff0c;配…

51串口通讯

介绍 串口是一种应用十分广泛的通讯接口&#xff0c;串口成本低、容易使用、通信线路简单&#xff0c;可实现两个设备的互相通信。单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信&#xff0c;极大的扩展了单片机的应用范围&#xff0…

基于VTK9.3.0+Visual Studio2017 c++实现DICOM影像MPR多平面重建+V R体绘制4个视图展示功能的实现

开源库&#xff1a;VTK9.3.0 开发工具&#xff1a;Visual Studio2017 开发语言&#xff1a;C 实现过程&#xff1a; class vtkImageInteractionCallback : public vtkCommand { public:static vtkImageInteractionCallback* New(){return new vtkImageInteractionCallback()…

文库小程序搭建部署:实现资源共享正向反馈

文档库相信大家应该不陌生&#xff0c;日常我们的工作模板、会议模板、求职时的简历模板、教育界的教学模板等来源方式都出自于文档库&#xff0c;随着互联网的发展和工作需求&#xff0c;文档模板开启了新型的知识变现新途径&#xff0c;通过文库小程序&#xff0c;我们不仅能…

Web服务器与Apache(LAMP架构+搭建论坛)

一、Web基础 1.HTML概述 HTML&#xff08;Hypertext Markup Language&#xff09;是一种标记语音,用于创建和组织Web页面的结构和内容&#xff0c;HTML是构建Web页面的基础&#xff0c;定义了页面的结构和内容&#xff0c;通过标记和元素来实现 2.HTML文件结构 <html>…

压缩pdf文件大小在线,在线免费压缩pdf

在现在办公中&#xff0c;PDF文档已经成为我们日常工作中不可或缺的一部分。然而&#xff0c;随着文档内容的不断丰富&#xff0c;PDF文件的大小也逐渐增大&#xff0c;这不仅占用了大量的存储空间&#xff0c;而且在传输和共享时也显得尤为不便。所以有时候我们需要把pdf压缩小…

# Kafka_深入探秘者(4):kafka 主题 topic

Kafka_深入探秘者&#xff08;4&#xff09;&#xff1a;kafka 主题 topic 一、kafka 主题管理 1、kafka 创建主题 topic 命令 1&#xff09;命令&#xff1a; # 切换到 kafka 安装目录 cd /usr/local/kafka/kafka_2.12-2.8.0/# 创建一个名为 heima 的 主题 bin/kafka-topic…

揭秘!速卖通卖家如何靠自养号测评打造爆款?

然而&#xff0c;许多商家对测评的认识存在严重的误区&#xff0c;他们错误地以为仅仅通过几次草率的测评就能快速塑造出爆款产品。实际上&#xff0c;测评远非如此简单&#xff0c;它是一个需要深思熟虑、精心策划和持续投入的过程。测评的真正价值在于帮助平台精准地把握产品…

Java-LinkedList和ArrayList的区别、Get/Add操作性能分析以及常见的遍历方式

LinkedList和ArrayList的区别、Get/Add操作性能分析以及常见的遍历方式 一、LinkedList基本特性主要方法 二、ArrayList初始化及基本操作ArrayList注意点&#xff08;待完善&#xff09;代码示例 三、ArrayList与LinkedList的区别四、Get/Add操作性能分析五、LinkedList遍历方式…

中霖教育:二级建造师报名后缺考有影响吗?

在完成二级建造师的报名程序后&#xff0c;考生无法进行退考。如果是不参加考试&#xff0c;可以选择弃考。弃考对个人并没有负面影响&#xff0c;缺席考试的话也不会被记录在个人诚信档案中。当然&#xff0c;如果弃考的话此次考试的成绩将被记为0&#xff0c;下一年参加考试按…

关于电机的线性思考

当大多数工程师听到电机这个词时&#xff0c;他们自然地想到旋转装置&#xff0c;例如有刷直流、无刷直流、步进电机或变频原动机。但是电机不一定是旋转的&#xff0c;很多时候设计需要直线运动。一种解决方案是添加某种齿轮或皮带装置来转换旋转运动&#xff0c;这种解决方案…

基于SpringBoot的实习管理系统设计与实现

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a; Java 数据库&#xff1a; MySQL 技术&#xff1a; SpringBoot框架&#xff0c;B/S模式 工具&#xff1a; MyEclipse&#xff0c;Tomcat 系统展示 …

预备役二招算法测试题解

这次题目出的都是一些偏向于基础的题目&#xff0c;就是一些简单的模拟&#xff0c;思维&#xff0c;以及基础算法&#xff08;二分&#xff0c;前缀和&#xff09; &#xff08;点击题目标题&#xff0c;进入原题&#xff09; 我是签到题 题解&#xff1a;就是说给你 t 组数据…

每日鲜语携手中国国家高尔夫球队队员殷若宁征战巴黎,打响中国高端鲜奶品牌“鲜”声量

近日&#xff0c;高端鲜奶品牌每日鲜语宣布携手蒙牛品牌代言人、中国国家高尔夫球队队员殷若宁&#xff0c;共赴巴黎奥运赛场&#xff0c;为梦想挥杆而上。邀请众多消费者开启高品质、健康的生活方式。此举不仅彰显了每日鲜语作为高端鲜奶新标杆的品牌定位&#xff0c;也同时延…

vue2.0项目安装依赖 sass 报错

1、报错代码&#xff1a; 2、原因&#xff1a;项目有点老&#xff0c;vue2的版本&#xff0c;所以node-sass在npm安装的时候大概率的会安装出错&#xff0c;或下载时间过长&#xff0c;因此考虑用dart-sass来替换。 npm install node-sassnpm:dart-sass3、然后就可以成功运行了…

8.项目结构——黑马程序员Java最新AI+若依框架项目

目录 前言一、后端1.ruoyi-admin2.ruoyi-common3.ruoyi-framework4. ruoyi-generator(可删除)5.ruoyi-quartz&#xff08;可删除&#xff09;5.ruoyi-system6. ruoyi-ui7.sql8.依赖关系9. 总结 二、前端三、SQL 前言 提示&#xff1a;本篇叙述若依前后端项目结构 一、后端 1…

无线领夹麦克风哪个品牌音质最好,揭秘无线麦克风哪个牌子最好!

​在这个数字化、信息化的时代&#xff0c;短视频和直播已经成为了人们生活中不可或缺的一部分。而无线麦克风&#xff0c;则是这些活动中不可或缺的重要工具。它们能够轻松捕捉声音&#xff0c;让内容更加生动、真实。然而&#xff0c;市场上的无线麦克风种类繁多&#xff0c;…

51-60 CVPR 2024 最佳论文 | Generative Image Dynamics

在2023年11月&#xff0c;谷歌研究院发布了一项令人瞩目的研究成果——Generative Image Dynamics&#xff08;生成图像动力学&#xff09;。这项技术的核心是将静态的图片转化为动态的、无缝循环的视频&#xff0c;而且更令人兴奋的是&#xff0c;这些生成的视频还具有交互性。…