尝试检测自行创建的DeadLock

时间:2018-11-08 12:55:23

标签: java multithreading deadlock

我编写了下面的Java代码来创建死锁,我将资源String变量传递给线程,并使用 synchronized 块将其锁定,并在其中建立了无限循环,这样第一个线程就永远不会永远离开它,所以第二个线程将永远无法访问它。

set serveroutput on
set linesize 2000        --> this
spool ..

然后在另一个窗口中,我编写了如下代码来检测死锁,

public class MainClass {

    public static void main(String[] args) {
        String resourcs = "testResource";
        MainClass M = new MainClass();
        Thread firstThread = new Thread(M.new MyThread("First",resourcs));
        Thread seconThread =  new Thread(M.new MyThread("Second",resourcs));
        firstThread.start();
        seconThread.start();

    }

    class MyThread implements Runnable{
        String resource;
        String name;
        public MyThread(String name,String resource) {
            this.resource = resource;
            this.name = name;
        }

        @Override
        public void run() {
            synchronized (resource) {
                while(true) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Still working on the thread :"+name);

                }
            }
        }

    }
}

但是看门狗什么也没发现。


  1. 我是否正确创建了死锁?(我想是的,因为控制台仅打印第一个线程的代码)
  2. 我是否需要等待一段时间(idk多少)才能使“看门狗”代码检测到死锁?

2 个答案:

答案 0 :(得分:4)

您的代码中没有死锁。当两个(或更多)线程互相等待时,就会发生死锁。这里不是这种情况。一个线程正在等待,另一个线程处于活动状态(处于无限循环中,但这并不意味着它处于死锁状态。)

答案 1 :(得分:1)

获得死锁的一种方法是乱序同步。本示例使两个线程死锁,然后使用上面的检查器找到它们。都可以从主要方法运行。

    final Object a = new Object();
    final Object b = new Object();
    CountDownLatch latch = new CountDownLatch(2);

    new Thread(()->{
        System.out.println(Thread.currentThread().getId() + " running");
        synchronized(a){    
            try{
                latch.countDown();
                latch.await();
            } catch(InterruptedException e){
                return;
            }
            synchronized(b){
                System.out.println("no deadlock");  
            }
        }   

    }).start();


    new Thread(()->{
        System.out.println(Thread.currentThread().getId() + " running");
        synchronized(b){
            try{
                latch.countDown();
                latch.await();
            } catch(InterruptedException e){
                return;
            }
            synchronized(a){
                System.out.println("no deadlock");  
            }
        }   

    }).start();

通过添加一个小的延迟,我可以找到两个死锁的线程ID。

    Thread.sleep(100);
    ThreadMXBean bean = ManagementFactory.getThreadMXBean();
    long[] threadIds = bean.findDeadlockedThreads();
    for(long id: threadIds){
        System.out.println(id + " deadlocked");
    }

然后输出如下:

  

正在跑步18

     

19个跑步

     

19个僵局

     

18个死锁

Thread.sleep可以省略,但是存在竞争条件。 bean.findDeadlockedThreads();可能会在出现死锁之前发生。即使有睡眠也有比赛条件,但这种情况很少发生。闩锁可以保证。

可以删除CountDownLatch,但是有时线程只会死锁。有时,一个线程会在另一个线程开始之前完成。