通过java自带的工具和linux命令来分析死锁

本文通过一个具体的Java程序示例,详细分析了如何使用jstack工具诊断并解决死锁问题,帮助读者理解死锁产生的原因及其解决方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  当我们编写java程序时,由于不合理的设计,可能会出现程序死循环/死锁问题。

下面我就以程序的死锁为例,来进行分析

我编写的测试类是Run类

1.查找Run类对应的PID,使用命令:ps -ef | grep Run

 

gl    6765  4121  0 13:52 ?        00:00:00 /opt/java/jdk1.8.0_101/bin/java -Dfile.encoding=UTF-8 -classpath /home/lupeng/java_development/MultiThread/bin Run
gl    6795  2766  0 13:53 pts/0    00:00:00 grep --color=auto Run

 

 

2.利用java自带的工具jstack进行分析

jstack 6765

结果如下

 

Java stack information for the threads listed above:
===================================================
"Thread-1":
	at DeadThread.run(DeadThread.java:37)
	- waiting to lock <0x00000000ec1df068> (a java.lang.Object)
	- locked <0x00000000ec1df078> (a java.lang.Object)
	at java.lang.Thread.run(Thread.java:745)
"Thread-0":
	at DeadThread.run(DeadThread.java:21)
	- waiting to lock <0x00000000ec1df078> (a java.lang.Object)
	- locked <0x00000000ec1df068> (a java.lang.Object)
	at java.lang.Thread.run(Thread.java:745)

Found 1 deadlock.


deadlock说明出现死锁问题。

 

Thread-1 已经获得了锁<0x00000000ec1df078>,同时等待锁<0x00000000ec1df078>

Thread-0已经获得了锁<0x00000000ec1df078>,同时等待锁<0x00000000ec1df078>

一次发生了死锁问题。

 

Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x00007fefcc003828 (object 0x00000000ec1df068, a java.lang.Object),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x00007fefcc006218 (object 0x00000000ec1df078, a java.lang.Object),
  which is held by "Thread-1"

 

 

 

 

 

那么到底时什么地方出现了死锁问题呢?

我们再来分析下

 

Java stack information for the threads listed above:
===================================================
"Thread-1":
	at DeadThread.run(DeadThread.java:37)
	- waiting to lock <0x00000000ec1df068> (a java.lang.Object)
	- locked <0x00000000ec1df078> (a java.lang.Object)
	at java.lang.Thread.run(Thread.java:745)
"Thread-0":
	at DeadThread.run(DeadThread.java:21)
	- waiting to lock <0x00000000ec1df078> (a java.lang.Object)
	- locked <0x00000000ec1df068> (a java.lang.Object)
	at java.lang.Thread.run(Thread.java:745)

Found 1 deadlock.

其中有一行是at DeadThread.run(DeadThread.java:37)

 

说明Thread-1实在DeadThread类的37行处发生死锁

其中at DeadThread.run(DeadThread.java:21)

说明Thread-0实在DeadThread类的21行处发生死锁
接下来我们定位到具体代码:

 

public class DeadThread implements Runnable{
	public String username;
	public Object lock1 = new Object();
	public Object lock2 = new Object();
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		if(username.equals("a")){
			synchronized (lock1) {
				try {
					System.out.println("username = "+username);
					System.out.println(Thread.currentThread().getName());
					Thread.sleep(3000);
				} catch (Exception e) {
					// TODO: handle exception
					e.printStackTrace();
				}
				synchronized (lock2) {
					System.out.println("按lock1->lock2的顺序执行代码");
				}
			}
		}
		if(username.equals("b")){
			synchronized (lock2) {
				try{
						System.out.println("username = "+username);
						System.out.println(Thread.currentThread().getName());
						Thread.sleep(3000);
					
				}catch (Exception e) {
					// TODO: handle exception
					e.printStackTrace();
				}
				synchronized (lock1) {
					System.out.println("按lock2->lock1顺序执行代码");
				}
			}
			
		}
	}
	
	public void setFlag(String username){
		this.username=username;
	}
}

 

 

从而定位到死锁发生的原因,及具体位置:

Thread-0获得了锁lock1,接下来期望获得锁lock2,(20)

但是此时Thread-1获得了锁lock2,接下来期望获得锁lock2,(37)

因而发生了死锁。
 

 

 

<think>好的,用户问的是如何在Linux下查看Java进程的命令。首先,我需要回忆常用的Linux命令,比如psjps。ps是查看进程的标准工具,结合grep过滤出Java进程。而jps是JDK自带工具,专门用于查看Java进程,更加方便。 然后,我需要详细解释每个命令的使用方法。比如用ps aux | grep java,这里要说明每个参数的含义,a表示所有用户,u显示详细信息,x包括没有控制终端的进程。同时,要提醒用户grep可能会出现自己这条命令的进程,可以用grep -v grep来排除。 接下来是jps命令,需要说明它位于JDK的bin目录下,可能需要配置环境变量才能直接使用。jps会列出进程ID主类名,可能还会显示参数,比如使用-l显示完整包名,-m显示传递给main方法的参数,-v显示JVM参数。 然后,用户可能需要进一步的信息,比如如何根据进程ID查看详细信息,这时候可以用jinfo、jstack等工具,或者直接查看/proc目录下的进程信息。例如,jinfo可以查看JVM的配置参数,jstack用于线程转储,分析线程问题。 最后,要确保用户明白这些命令的适用场景,比如ps适用于所有进程,而jps专门针对Java进程,更加简洁。同时提醒权限问题,可能需要sudo来查看其他用户的进程。 在相关问题部分,应该围绕Java进程管理监控展开,比如如何查看堆内存使用情况(jstat),如何生成堆转储(jmap),如何分析线程死锁(jstack),以及如何调整JVM参数(jinfo)。这些问题都是用户在使用上述命令后可能会遇到的后续步骤,保持逻辑连贯性。</think><< 在Linux系统中查看Java进程的常用命令及说明: 1. `ps aux | grep java` ```bash ps aux | grep java ``` - `ps aux`:显示所有用户的所有进程 - 管道符`|`将结果传递给`grep java`过滤出包含"java"的进程 - 可能包含grep进程本身,可以使用`grep -v grep`排除 - 示例输出: ``` user 1234 0.5 2.1 1234567 67890 ? Sl 10:00 0:15 java -jar myapp.jar ``` 2. `jps`命令Java Virtual Machine Process Status Tool) ```bash jps -lvm ``` - JDK自带Java进程查看工具(位于$JAVA_HOME/bin目录) - `-l`:显示完整包名/应用主类全名 - `-m`:显示传递给main()方法的参数 - `-v`:显示传递给JVM的参数 - 示例输出: ``` 1234 com.example.MainApp -Dconfig=prod.conf 5678 sun.tools.jps.Jps -lvm ``` 3. 查看详细进程信息 ```bash # 查看JVM参数 jinfo <pid> # 查看线程堆栈 jstack <pid> # 查看内存使用 jstat -gc <pid> # 查看/proc目录下的进程信息 ls -l /proc/<pid>/exe ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值