代码之家  ›  专栏  ›  技术社区  ›  nobalG

尝试检测自创的死锁

  •  -2
  • nobalG  · 技术社区  · 7 年前

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

    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);
    
                    }
                }
            }
    
        }
    }
    

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

    import java.lang.management.ManagementFactory; 
    import java.lang.management.ThreadInfo;
    import java.lang.management.ThreadMXBean;
    
    public class DetectDeadLock {
        public static void main(String args[]) {
            ThreadMXBean bean = ManagementFactory.getThreadMXBean();
            long[] threadIds = bean.findDeadlockedThreads();
    
            if (threadIds != null) {
                ThreadInfo[] infos = bean.getThreadInfo(threadIds);
    
                for (ThreadInfo info : infos) {
                    StackTraceElement[] stack = info.getStackTrace();
                    System.out.println("here");
                    // Log or store stack trace information.
                }
            }
    
        }
    }
    


    1. 我是否正确创建了死锁? (我想是的,因为控制台只打印第一个线程的代码)
    2. 我要等一段时间吗 (idk)多少钱让“看门狗”代码检测死锁?
    2 回复  |  直到 7 年前
        1
  •  1
  •   Community Mohan Dere    6 年前

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

        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();

    倒计时锁存器可以被移除,但是线程有时只会死锁。其他时候,一个线程将在另一个线程开始之前完成。

        2
  •  4
  •   Max Vollmer    7 年前