实战

准备项目

随便找个SpringBoot项目

  1. package com.example.demo;
  2. /**
  3. */
  4. public class DeadLockTest extends Thread {
  5. private String first;
  6. private String second;
  7. public DeadLockTest(String name, String first, String second) {
  8. super(name);
  9. this.first = first;
  10. this.second = second;
  11. }
  12. public void run() {
  13. synchronized (first) {
  14. try {
  15. System.out.println(this.getName() + " ...synchronized:===> first " + first);
  16. Thread.sleep(1000L);
  17. synchronized (second) {
  18. System.out.println(this.getName() + " ...synchronized:===> second " + second);
  19. }
  20. } catch (InterruptedException e) {}
  21. }
  22. }
  23. public static void main(String[] args) throws InterruptedException {
  24. String lockA = "lockA";
  25. String lockB = "lockB";
  26. DeadLockTest t1 = new DeadLockTest("t1", lockA, lockB);
  27. DeadLockTest t2 = new DeadLockTest("t2", lockB, lockA);
  28. t1.start();
  29. t2.start();
  30. t1.join();
  31. t2.join();
  32. }
  33. }
  1. package com.example.demo;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.web.bind.annotation.GetMapping;
  5. import org.springframework.web.bind.annotation.RestController;
  6. @SpringBootApplication
  7. @RestController
  8. public class DemoApplication {
  9. public static void main(String[] args) {
  10. SpringApplication.run(DemoApplication.class, args);
  11. }
  12. @GetMapping("/hello")
  13. public String c_ () throws InterruptedException {
  14. String lockA = "lockA";
  15. String lockB = "lockB";
  16. DeadLockTest t1 = new DeadLockTest("t1", lockA, lockB);
  17. DeadLockTest t2 = new DeadLockTest("t2", lockB, lockA);
  18. t1.start();
  19. t2.start();
  20. t1.join();
  21. t2.join();
  22. return "你好";
  23. }
  24. }

打包部署

这个我就不演示了,将你自己的项目打包, 部署到 linux上,这个我就不演示了,,大家都会.

访问网址

浏览器get请求敲击url: http://zjj101:8080/demo/hello ,发现浏览器一直在转圈圈,说明一直访问不通.

看tomcat日志发现已经是死锁状态了.

  1. t1 ...synchronized:===> first lockA
  2. t2 ...synchronized:===> first lockB

使用jstack工具

查看进程号

使用 ps -ef|grep java 命令查看到Java进程是11271

[root@zjj101 logs]# ps -ef|grep java
root      11271      1  3 09:45 pts/0    00:00:24 /usr/bin/java -Djava.util.logging.config.file=/root/apache-tomcat-8.5.28/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dignore.endorsed.dirs= -classpath /root/apache-tomcat-8.5.28/bin/bootstrap.jar:/root/apache-tomcat-8.5.28/bin/tomcat-juli.jar -Dcatalina.base=/root/apache-tomcat-8.5.28 -Dcatalina.home=/root/apache-tomcat-8.5.28 -Djava.io.tmpdir=/root/apache-tomcat-8.5.28/temp org.apache.catalina.startup.Bootstrap start

将日志导出到文件中

使用 jstack -l [进程号]>deadlock.jstack 命令将日志导出到deadlock.jstack文件中

[root@zjj101 logs]# jstack -l 11271 >deadlock.jstack
[root@zjj101 logs]# ls
catalina.2021-10-12.log      localhost.2021-10-12.log
catalina.out                 localhost_access_log.2021-10-12.txt
deadlock.jstack              manager.2021-10-12.log
host-manager.2021-10-12.log

查看日志文件

使用less命令查看,

敲击命令: less deadlock.jstack

然后打开文件一直翻,直到找到 “Found one Java-level deadlock:”字眼的东西,

然后看”Java stack information for the threads listed above:”下的内容, 上面说了两个线程在 DeadLockTest.java:21 行锁住了.

Found one Java-level deadlock:
=============================
"t2":
  waiting to lock monitor 0x00007f61983ba9e8 (object 0x00000000e90f32c8, a java.lang.String),
  which is held by "t1"
"t1":
  waiting to lock monitor 0x00007f61983bfe78 (object 0x00000000e90f3300, a java.lang.String),
  which is held by "t2"

Java stack information for the threads listed above:
===================================================
"t2":
        at com.example.demo.DeadLockTest.run(DeadLockTest.java:21)
        - waiting to lock <0x00000000e90f32c8> (a java.lang.String)
        - locked <0x00000000e90f3300> (a java.lang.String)
"t1":
        at com.example.demo.DeadLockTest.run(DeadLockTest.java:21)
        - waiting to lock <0x00000000e90f3300> (a java.lang.String)
        - locked <0x00000000e90f32c8> (a java.lang.String)

Found 1 deadlock.

查看你自己写的代码

发现的确是这里锁住了,然后你就去修改代码即可

使用 jstack 排查Java项目的Linux线上环境死锁 - 图1