Java - 如何检测死锁并从中恢复?

时间:2016-04-03 04:46:20

标签: java multithreading synchronization deadlock synchronized

现在我编写了一个Java程序,其目的是检测死锁并从这种情况中恢复。程序输入是两个数字,N =资源类型数,M =进程数。

我想做这样的事情:

private static void test2() {
    final ReentrantLock lock1 = new ReentrantLock();
    final ReentrantLock lock2 = new ReentrantLock();

    Thread thread1 = new Thread(new Runnable() {
        @Override public void run() {
            try {
                lock1.lock();
                System.out.println("Thread1 acquired lock1");
                try {
                    TimeUnit.MILLISECONDS.sleep(50);
                } catch (InterruptedException ignore) {}
                lock2.lock();
                System.out.println("Thread1 acquired lock2");
            }
            finally {
                lock2.unlock();
                lock1.unlock();
            }
        }
    });
    thread1.start();

    Thread thread2 = new Thread(new Runnable() {
        @Override public void run() {
            try {
                lock2.lock();
                System.out.println("Thread2 acquired lock2");
                try {
                    TimeUnit.MILLISECONDS.sleep(50);
                } catch (InterruptedException ignore) {}
                lock1.lock();
                System.out.println("Thread2 acquired lock1");
            }
            finally {
                lock1.unlock();
                lock2.unlock();
            }
        }
    });
    thread2.start();

    // Wait a little for threads to deadlock.
    try {
        TimeUnit.MILLISECONDS.sleep(100);
    } catch (InterruptedException ignore) {}

    detectDeadlock();
}  

但不是2,N锁定,我有几个问题这样做。我的代码在这里尝试:

class Main {
    private static int MAX_AVAILABLE = 10;
    private static int IDLE = 1000;

    public static void main(String[] args) throws java.lang.Exception{
        int n, m; //number of resources and process, respectively
        ReentrantLock[] resources; // Locks for resources
        int[] available; // Number of instances per resource
        Process[] processes; // Processes array
        DeadlockDetector supervisor; // Deadlock detaction class

        n = Integer.valueOf(args[0]);
        m = Integer.valueOf(args[1]);

        resources = new ReentrantLock[n];
        available = new int[n];
        processes = new Process[m];
        supervisor = new DeadlockDetector();

        // Create resources array
        for(int i=0; i<n; ++i){
            available[i] = (int)(Math.floor(Math.random()*MAX_AVAILABLE + 1));
            resources[i] = new ReentrantLock();
            System.out.println("R"+String.valueOf(i+1)+"-> instances: "+String.valueOf(available[i]));
        }

        // Creating processes
        for(int i=0; i<m; ++i){
            processes[i] = new Process(i, resources, available, n);
            System.out.println("P"+String.valueOf(i+1)+"-> requested "+Arrays.toString(processes[i].requested));
            processes[i].start();
        }
        //Run deadlock detection
        try {
            TimeUnit.MILLISECONDS.sleep(IDLE);
        }catch (InterruptedException ignore){}

        supervisor.start();
     }
}
class Process extends Thread{
    public int id;
    public int total; // Total of resources instances needed for finished the process
    public ReentrantLock[] resources;
    public int[] requested; // Number of instances needed per resource type
    public boolean[] needed; // Boolean indicating whether the process needs at least one instance of the resource i 
    public int n;
    private static int MIN_TIME = 1000;
    private static int MAX_TIME = 3000;

    public Process(int index, ReentrantLock[] res, int[] available, int n_resources){
       id = index;
       n = n_resources;
       resources = res;

       total = 0; 
       requested = new int[n];
       needed = new boolean[n];

       for(int i=0; i<n; ++i){
            requested[i] = (int)(Math.floor(Math.random()*available[i]));
            needed[i] = requested[i] > 0;
            total += requested[i];
       }
    }

    @Override
    public void run(){
        int resourceT = 0;
        int timeToSleep;

        System.out.println("P"+String.valueOf(id+1)+" begin running");
        try{
            while(total > 0){
                resourceT = (int)(Math.floor(Math.random()*n));
                if(requested[resourceT] < 1){
                    System.out.println("P"+String.valueOf(id+1)+"-> I do not need more R"+String.valueOf(resourceT+1));
                    continue;
                }
                System.out.println("P"+String.valueOf(id+1)+"-> I'll take R"+String.valueOf(resourceT+1));
                resources[resourceT].lock();
                timeToSleep = (int)(Math.floor(Math.random()*(MAX_TIME - MIN_TIME)) + MIN_TIME);
                try{
                    TimeUnit.MILLISECONDS.sleep(timeToSleep);
                }catch (InterruptedException ignore){}
                --total;
                --requested[resourceT];
            }
        }finally{
            for(int i=0; i<n; ++i){
                if(needed[i] && resources[i].isHeldByCurrentThread())
                    resources[i].unlock();
            }
        }
        System.out.println("P"+String.valueOf(id+1)+"-> Im finished");
    }
}

class DeadlockDetector extends Thread{
    public ThreadMXBean threadBean;
    public long[] threadIds;

    public DeadlockDetector(){
    }

    @Override
    public void run(){
        Boolean good;
        this.threadBean = ManagementFactory.getThreadMXBean();

        threadIds = threadBean.findDeadlockedThreads();
        int deadlockedThreads = threadIds != null? threadIds.length : 0;

        if(deadlockedThreads>1){
            good = false;
            System.out.println("Number of deadlocked threads: " + deadlockedThreads);
            //recoverDeadlock();
            //break;
        }
}
public void recoverDeadlock(){
}
}

拜托,有人可以帮我修复这个细节吗?谢谢!

0 个答案:

没有答案