Java系列[多线程并发] -- 关于死锁的讲解与排查

  

因为热爱所以坚持,因为热爱所以等待。熬过漫长无戏可演的日子,终于换来了人生的春天,共勉!!!

1.什么是死锁?

①死锁:两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力干涉那它们都将无法推进下去,如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁。

②原因:

  • 系统资源不足
  • 进程运行推进的顺序不合适
  • 资源分配不当
     

③示意图:

为了更好看清什么是死锁,我们通过代码来写一个死锁

2.编写一个死锁

 流程:

  • ①编写资源类
  • ②线程取得自己的锁,同时想去获取别人的锁(吃着碗里的,看着锅里的)
  • ③创建两个线程执行

代码:

package JUC;
import java.util.concurrent.TimeUnit;
class HoldLockThread implements Runnable {
	private String lock1;
	private String lock2;
	
	public HoldLockThread(String lock1, String lock2) {
		super();
		this.lock1 = lock1;
		this.lock2 = lock2;
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		synchronized (lock1) {
			System.out.println(Thread.currentThread().getName()+"\t 自己持有:"+lock1+"\t 尝试获取: " + lock2);
			
			try {TimeUnit.SECONDS.sleep(2);} catch (Exception e) {e.printStackTrace();}
			
			synchronized (lock2) {
				System.out.println(Thread.currentThread().getName()+"\t 自己持有:"+lock2+"\t 尝试获取: " + lock1);
			}
		}
	}	
} 

public  class DeathLockDemo {
    public static void main(String[] args) {
        String lockA= "lockA";
        String lockB= "lockB";

        new Thread(new HoldLockThread(lockA,lockB),"ThreadA").start();
        new Thread(new HoldLockThread(lockB,lockA),"ThreadB").start();
    }
}

执行结果:程序一直运行

ThreadA	 自己持有:lockA	 尝试获取: lockB
ThreadB	 自己持有:lockB	 尝试获取: lockA

3.如何排查

①jps -l 查找java进程

C:\Users\ASUS>jps -l
13460 jdk.jcmd/sun.tools.jps.Jps
9716 C:\Users\ASUS\Desktop\JAva\eclipse\\plugins/org.eclipse.equinox.launcher_1.5.400.v20190515-0925.jar
17256 JUC.DeathLockDemo

找到我们直接写的类的进程号 

②jstack 找到死锁查看相关信息

C:\Users\ASUS>jstack 17256
2021-10-02 18:00:52
Full thread dump Java HotSpot(TM) 64-Bit Server VM (11.0.8+10-LTS mixed mode):

//省略部分信息

Found one Java-level deadlock:
=============================
"ThreadA":
  waiting to lock monitor 0x00000232780e2080 (object 0x0000000089a5deb8, a java.lang.String),
  which is held by "ThreadB"
"ThreadB":
  waiting to lock monitor 0x00000232780e1c80 (object 0x0000000089a5de88, a java.lang.String),
  which is held by "ThreadA"

Java stack information for the threads listed above:
===================================================
"ThreadA":
        at JUC.HoldLockThread.run(DeathLockDemo.java:22)
        - waiting to lock <0x0000000089a5deb8> (a java.lang.String)
        - locked <0x0000000089a5de88> (a java.lang.String)
        at java.lang.Thread.run([email protected]/Thread.java:834)
"ThreadB":
        at JUC.HoldLockThread.run(DeathLockDemo.java:22)
        - waiting to lock <0x0000000089a5de88> (a java.lang.String)
        - locked <0x0000000089a5deb8> (a java.lang.String)
        at java.lang.Thread.run([email protected]/Thread.java:834)

Found 1 deadlock.

③定位死锁的位置

通过对jstack输出信息的分析,我们可以看出死锁产生的具体位置以及原因,完美解决!!!

 

我之前写过一篇关于JVM排查命令的文章,里面详细介绍了这些指令,感兴趣的小伙伴可以去看一看:深入理解Java虚拟机系列 --13 性能监控与调优篇 --01JVM命令行监控工具因为热爱所以坚持,因为热爱所以等待。熬过漫长无戏可演的日子,终于换来了人生的春天,共勉!!!1.性能指标①.停顿时间(或响应时间)②.吞吐量③.并发数④.内存占用⑤.相互间的关系下一篇 14 性能监控与调优篇02参考视频 :尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机)参考书籍 : 深入理解Java虚拟机...https://blog.csdn.net/qq_43295483/article/details/120382134?spm=1001.2014.3001.5501

猜你喜欢

转载自blog.csdn.net/qq_43295483/article/details/120587565