通过jvisualvm查看产生死锁线程

来源:互联网 发布:安卓鼓机软件loopz 编辑:程序博客网 时间:2024/05/01 02:03

产生死锁的原因

(1) 因为系统资源不足。
(2) 进程运行推进的顺序不合适。
(3) 资源分配不当等。

产生死锁的四个必要条件

(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。


锁是一个非常有用的工具,运用场景非常多,因为他使用起来非常简单,而且易于理解。但同时它也带来一些困扰没那就是可能会引起死锁,一旦产生死锁,就会造成系统功能不可用。让我们先来看一段代码,这段代码会引起死锁,使线程t1和线程t2互相等待对方释放锁。


public class DeadLockDemo {    private static String A="A";    private static String B="B";    public static void main(String[] args){        new Main().deadLock();    }    private void deadLock(){        Thread t1 = new Thread(new Runnable() {            @Override            public void run() {                synchronized(A){                    try{                        Thread.currentThread().sleep(2000);                    }catch (InterruptedException e){                        e.printStackTrace();                    }                    synchronized(B){                        System.out.println("1");                    }                }            }        });        Thread t2= new Thread(new Runnable() {            @Override            public void run() {                synchronized(B){                    synchronized(A){                        System.out.println("2");                    }                }            }        });        t1.start();        t2.start();    }}

jvisualvm 查看Dump线程

在JDK 的 bin 目录下可以找到, jvisualvm.exe(Windows) jvisualvm(OSX/Linux)。如果你已经将Java环境加入到了系统环境当中的话,可以直接在命令行下,输入jvisualvm运行。
双击启动 Java VisualVM 后可以看到窗口左侧 “应用程序 ”栏中有“ 本地 ”、“远程 ” 、“快照 ”三个项目。
“本地 ”下显示的是在 localhost 运行的 Java 程序的资源占用情况,如果本地有 Java 程序在运行的话启动 Java VisualVM 即可看到相应的程序名,点击程序名打开相应的资源监控菜单,以图形的形式列出程序所占用的 CPU 、 Heap 、 PermGen 、类、线程的 统计信息。
“远程” 项下列出的远程主机上的 Java 程序的资源占用情况,但需要在远程主机上运行 jstatd 守护程序

这里写图片描述

从上图可知,检测到死锁,可以通过【线程Dump】查看具体的死锁线程的信息。
这里写图片描述

Found one Java-level deadlock: //发现死锁线程============================="Thread-1":  waiting to lock monitor 0x00007f9ded0208b8 (object 0x000000076f598560, a java.lang.String),  which is held by "Thread-0""Thread-0":  waiting to lock monitor 0x00007f9ded021ca8 (object 0x000000076f598578, a java.lang.String),  which is held by "Thread-1"Java stack information for the threads listed above:==================================================="Thread-1":    at Main$2.run(Main.java:36)    - waiting to lock <0x000000076f598560> (a java.lang.String)    - locked <0x000000076f598578> (a java.lang.String)    at java.lang.Thread.run(Thread.java:745)"Thread-0":    at Main$1.run(Main.java:25)    - waiting to lock <0x000000076f598578> (a java.lang.String)    - locked <0x000000076f598560> (a java.lang.String)    at java.lang.Thread.run(Thread.java:745)Found 1 deadlock.

可以看到
Main.Java 25行:Thread-0房钱锁定了<0x000000076f598560>,并且在等待锁定<0x000000076f598578>
Main.Java 36行:Thread-1当前锁定了<0x000000076f598578>,并且在等待锁定<0x000000076f598560>

两个进程互相都需要对方线程释放其所占有资源(java.lang.String),而根据【请求与保持条件】原则,显然不会释放已经到手的资源,可以说是吃着碗里的,看着锅里的,两边都想占有。


如何避免死锁?

  1. 避免一个线程同时获取多个锁
  2. 避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源。
  3. 尝试使用定时锁,使用lock.tryLock(timeout)来替代使用内部锁机制。
  4. 对于数据库锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况。
0 0
原创粉丝点击