通过jstack分析线程死锁场景

死锁的四个必要条件:互斥、持有并等待、不可抢占、循环等待。
死锁场景是两个线程各自持有某个锁,并试图获取对方持有的锁,导致互相等待。

创建死锁示例代码

package io.renren.controller;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;/*** 通过jstack分析线程死锁场景*/
@RestController
public class DeadlockController {// 定义两个互斥锁对象private final Object lockA = new Object();private final Object lockB = new Object();@GetMapping("/deadlock")public String triggerDeadlock() {new Thread(() -> {synchronized (lockA) {System.out.println("Thread1 acquired lockA");try { Thread.sleep(100); }catch (InterruptedException e) {}synchronized (lockB) {System.out.println("Thread1 acquired lockB");}}}, "Deadlock-Thread-1").start();new Thread(() -> {synchronized (lockB) {System.out.println("Thread2 acquired lockB");try { Thread.sleep(100); }catch (InterruptedException e) {}synchronized (lockA) {System.out.println("Thread2 acquired lockA");}}}, "Deadlock-Thread-2").start();return "死锁已触发,检查控制台日志和线程状态";}}

访问端点触发死锁

http://localhost:8080/deadlock

请添加图片描述

使用 jstack 分析

查找Java进程PID

jps -l
# 输出示例:
# 12345 com.example.DeadlockDemoApplication

生成线程转储

jstack -l 12345 > thread_dump.txt

请添加图片描述

分析线程转储:
请添加图片描述
死锁分析图解
请添加图片描述

解决死锁的方案

方案1:统一锁获取顺序

// 修改第二个线程的锁获取顺序
new Thread(() -> {synchronized (lockA) {  // 改为先获取lockASystem.out.println("Thread2 acquired lockA");try { Thread.sleep(100); } catch (InterruptedException e) {}synchronized (lockB) {System.out.println("Thread2 acquired lockB");}}
}, "Safe-Thread-2").start();

方案2:使用 tryLock 超时机制

//定义成员变量
private final ReentrantLock lock1 = new ReentrantLock();
private final ReentrantLock lock2 = new ReentrantLock();//在函数内部执行
new Thread(() -> {try {if (lock1.tryLock(1, TimeUnit.SECONDS)) {try {System.out.println("Thread1 acquired lock1");Thread.sleep(100);if (lock2.tryLock(1, TimeUnit.SECONDS)) {try {System.out.println("Thread1 acquired lock2");} finally {lock2.unlock();}}} finally {lock1.unlock();}}} catch (InterruptedException e) {e.printStackTrace();}
}).start();

预防死锁的最佳实践

锁顺序:统一所有线程的锁获取顺序

超时机制:使用 tryLock() 替代内置锁

减少锁粒度:避免在方法级别使用 synchronized

静态分析工具:使用 FindBugs/SpotBugs 检测潜在死锁

压力测试:使用 JMeter 模拟高并发场景

最后

实际开发中建议使用 ReentrantLock 等更灵活的工具替代 synchronized,并配合 Arthas 等在线诊断工具进行实时分析。

------------------------------------------------- jstack补充 -----------------------------------------------------
jstack命令用于打印指定Java进程、核心文件或远程调试服务器的Java线程的Java堆栈跟踪信息。

jstack命令可以生成JVM当前时刻的线程快照。线程快照是当前JVM内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。

如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。

当指定的进程在64位Java虚拟机上运行时,可能需要指定-J-d64选项,例如:jstack -J-d64 -m pid。

该命令可能在未来的版本中不可用!!!

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

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

相关文章

PyTorch梯度:深度学习的引擎与实战解析

一、梯度:深度学习中的指南针 1.1 什么是梯度? 梯度是函数在某一点变化率最大的方向及其大小,就像爬山时最陡峭的上坡方向。在深度学习中,梯度告诉我们如何调整神经网络参数,使损失函数最小化。 1.2 梯度的重要性 …

【Python爬虫】详细入门指南

目录 一、简单介绍 二、详细工作流程以及组成部分 三、 简单案例实现 一、简单介绍 在当今数字化信息飞速发展的时代,数据的获取与分析变得愈发重要,而网络爬虫技术作为一种能够从互联网海量信息中自动抓取所需数据的有效手段,正逐渐走入…

Golang|Channel 相关用法理解

文章目录 用 channel 作为并发小容器channel 的遍历channel 导致的死锁问题用 channel 传递信号用 channel 并行处理文件用channel 限制接口的并发请求量用 channel 限制协程的总数量 用 channel 作为并发小容器 注意这里的 ok 如果为 false,表示此时不仅channel为空…

Windows单机模拟MySQL主从复制

这里写自定义目录标题 下载MySQL ZIP压缩包安装主库1、创建配置文件2、安装服务3、初始化数据库4、启动服务5、配置主库 安装从库1、配置ini文件2、安装服务3、初始化数据库4、启动服务5、配置从库6、验证从库状态 操作主库验证 下载MySQL ZIP压缩包 https://dev.mysql.com/do…

OSPF路由引入

一、基本概念与作用 1.OSPF路由引入指通过自治系统边界路由器(ASBR)将外部路由(如BGP、RIP、静态路由或其他OSPF进程的路由)注入当前OSPF域,实现跨协议或跨区域的网络互通‌。 其核心作用包括: ‌扩展网…

弱口令爆破

1.简单介绍 弱口令是指一些简单易猜的密码,可通过社工方式和一些爆破工具进行破解,以下介绍一款爆破工具的用法。burpsuite简称BP,一款可以利用字典破解账户密码的工具。 2.部署网站 可以使用PHPstudy的Apache服务,也可以使用I…

Vue3+Vite前端项目部署后部分图片资源无法获取、动态路径图片资源报404错误的原因及解决方案

目录 Vue3vite前端项目部署后部分图片资源无法获取、动态路径图片资源报404错误的原因及解决方案 一、情景介绍 1、问题出现的场景 2、无法加载的图片写法 二、反向代理原理简介 三、造成该现象的原因 四、解决方案 1、放弃动态渲染 2、在页面挂载的时候引入图片资源 …

详解如何从零用 Python复现类似 GPT-4o 的多模态模型

🧠 向所有学习者致敬! “学习不是装满一桶水,而是点燃一把火。” —— 叶芝 我的博客主页: https://lizheng.blog.csdn.net 🌐 欢迎点击加入AI人工智能社区! 🚀 让我们一起努力,共创…

榕壹云无人共享系统:基于SpringBoot+MySQL+UniApp的物联网共享解决方案

无人共享经济下的技术革新 随着无人值守经济模式的快速发展,传统共享设备面临管理成本高、效率低下等问题。榕壹云无人共享系统依托SpringBootMySQLUniApp技术栈,结合物联网与移动互联网技术,为商家提供低成本、高可用的无人化运营解决方案。…

基于PHP的酒店网上订房系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 酒店服务是旅游行业的一个重要组成部分,它的作用已经从过去的单一的住宿、结算帐务向全面、高水平的服务型酒店转变。酒店的服务工作贯穿于整个酒店的市场营销、预定、入住、退房、结账等环节,酒店要提高整体工作水平,简化工作程序&…

【Linux生成SSH秘钥实现远程连接】Linux生成SSH秘钥对与修改服务配置文件实现无密码远程连接

文章目录 前言1. Linux 生成SSH秘钥对2. 修改SSH服务配置文件3. 客户端秘钥文件设置4. 本地SSH私钥连接测试5. Linux安装Cpolar工具6. 配置SSHTCP公网地址7. 远程SSH私钥连接测试8. 固定SSH公网地址9. 固定SSH地址测试 前言 在数字化江湖中,企业对各种技术的需求就…

# linux 设置宽容模式

linux 设置宽容模式 在Linux系统中,通常没有直接称为“宽容模式”的设置选项,但你可以通过几种方式来模拟或调整系统行为,使其表现得更加“宽容”,特别是在处理错误、权限问题或其他潜在问题时。以下是一些常见的方法&#xff1a…

【C++】——lambda表达式

🌟 前言:​​C Lambda表达式,当函数开始"叛逆期"​​ 你是否有过这样的崩溃瞬间? 为了写个​​只用到一次​​的排序规则,被迫定义了一个类在std::for_each里塞函数指针,代码瞬间变成"古董级"写法看着层的循环…

深入解析B站androidApp接口:从bilibili.api.ticket.v1.Ticket/GetTicket到SendMsg的技术分析

前言 最近一段时间,我对B站的App接口进行了深入分析,特别是关注了认证机制和私信功能的实现。通过逆向工程和网络抓包,发现了B站移动端API的底层工作原理,包括设备标识生成机制、认证流程和消息传输协议。本文将分享这些研究成果…

从零开始学A2A一:A2A 协议概述与核心概念

A2A 协议概述与核心概念 学习目标 基础理解 掌握A2A协议的基本概念和背景理解协议的设计原则和核心思想了解协议在AI领域的重要性 技术掌握 熟悉A2A协议的核心功能组件掌握能力发现和任务管理机制理解多模态交互和安全通信原则 实践应用 能够设计基于A2A的智能体系统掌握协议…

2025.04.10-拼多多春招笔试第三题

📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围OJ 03. 数字重排最大化问题 问题描述 LYA是一位专业的数字设计师。她手中有两个数字序列 s 1 s_1

苍穹外卖day04

Spring Task实现定时处理订单状态 作用:不需要输入提示信号,便可定时自动执行程序 使用步骤 1、启动类上加上注解(EnableScheduling)开启定时任务调度 2、专门创建一个包来管理执行定时任务的类,该类需要交给IOC容…

BFD:网络链路检测与联动配置全攻略

目录 BFD简介 BFD会话建立方式和检测机制 BFD会话建立过程 BFD工作流程 联动功能 BFD与OSPF联动配置需求 BFD与OSPF联动配置实现 BFD与VRRP联动配置需求 BFD与VRRP联动配置实现 单臂回声 BFD默认参数及调整方法 BFD简介 一种全网统一、检测迅速、监控网络中链…

【LLM】A2A 与 MCP:剖析 AI Agent 互联时代的两种关键协议

随着人工智能技术的飞速发展,AI Agent(智能体)正从理论走向实践,有望成为提升生产力的关键。然而,正如历史上任何新兴技术领域一样,标准的缺失导致了“筒仓效应”——不同来源、不同框架构建的 Agent 难以有…

免费下载 | 2025清华五道口:“十五五”金融规划研究白皮书

《2025清华五道口:“十五五”金融规划研究白皮书》的核心内容主要包括以下几个方面: 一、五年金融规划的重要功能与作用 凝聚共识:五年金融规划是国家金融发展的前瞻性谋划和战略性安排,通过广泛听取社会各界意见,凝…