Пытался обнаружить самостоятельно созданный DeadLock - PullRequest
0 голосов
/ 08 ноября 2018

Я написал приведенный ниже Java-код для создания тупика, я передал переменную ресурса String потокам и заблокировал ее, используя синхронизированный блок, и создал внутри него бесконечный цикл, так что первый поток никогда не будет никогда оставьте его, чтобы второй поток не смог получить к нему доступ навсегда.

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. Должен ли я подождать некоторое время (сколько, конечно), чтобы код 'Watch Dog' обнаружил тупик?

Ответы [ 2 ]

0 голосов
/ 08 ноября 2018

Один из способов получить взаимоблокировку - неупорядоченные синхронизации. Этот пример блокирует два потока и затем использует вышеупомянутую проверку, чтобы найти их. Все это можно запустить из основного метода.

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

Добавив небольшую задержку, я могу найти два тупиковых идентификатора потока.

    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 может быть удален, но тогда потоки будут иногда только тупиковыми. В других случаях один поток завершается до запуска другого.

0 голосов
/ 08 ноября 2018

В вашем коде нет тупика. Тупик возникает, когда два (или более) потока ждут друг друга. Это не тот случай, здесь. Один поток ожидает, другой активен (в бесконечном цикле, но это не значит, что он заблокирован).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...