FileDocCategorySizeDatePackage
DeadlockDetectingLock.javaAPI DocExample13487Sat May 29 22:21:50 BST 2004javathreads.examples.ch06

DeadlockDetectingLock

public class DeadlockDetectingLock extends ReentrantLock

Fields Summary
private static List
deadlockLocksRegistry
private List
hardwaitingThreads
private boolean
debugging
private static Lock
a
private static Lock
b
private static Lock
c
private static Condition
wa
private static Condition
wb
private static Condition
wc
Constructors Summary
public DeadlockDetectingLock(boolean fair, boolean debug)

        super(fair);
        debugging = debug;
        registerLock(this);
    
public DeadlockDetectingLock()

        this(false, false);
    
public DeadlockDetectingLock(boolean fair)

        this(fair, false);
    
Methods Summary
private static voidawaitSeconds(java.util.concurrent.locks.Condition c, int seconds)

        try {
             c.await(seconds, TimeUnit.SECONDS);
        } catch (InterruptedException ex) {
        }
    
private static synchronized booleancanThreadWaitOnLock(java.lang.Thread t, javathreads.examples.ch06.DeadlockDetectingLock l)

        Iterator locksOwned = getAllLocksOwned(t);
        while (locksOwned.hasNext()) {
            DeadlockDetectingLock current = (DeadlockDetectingLock) locksOwned.next();

            // Thread can't wait if lock is already owned. This is the end condition
            //      for the recursive algorithm -- as the initial condition should be
            //      already tested for.
            if (current == l) return false;

            Iterator waitingThreads = getAllThreadsHardwaiting(current);
            while (waitingThreads.hasNext()) {
                Thread otherthread = (Thread) waitingThreads.next();

                // In order for the thread to safely wait on the lock, it can't
                //   own any locks that have waiting threads that already owns
                //   lock. etc. etc. etc. recursively etc.
                if (!canThreadWaitOnLock(otherthread, l)) {
                    return false;
                }
            }
        }
        return true;
    
private static voiddelaySeconds(int seconds)


         
        try {
             Thread.sleep(seconds * 1000);
        } catch (InterruptedException ex) {
        }
    
private static synchronized voidfreeIfHardwait(java.util.List l, java.lang.Thread t)

        if (l.contains(t)) l.remove(t);
    
private static java.util.IteratorgetAllLocksOwned(java.lang.Thread t)

        DeadlockDetectingLock current;
        ArrayList results = new ArrayList();

        Iterator itr = deadlockLocksRegistry.iterator();
        while (itr.hasNext()) {
            current = (DeadlockDetectingLock) itr.next();
            if (current.getOwner() == t) results.add(current);
        }
        return results.iterator(); 
    
private static java.util.IteratorgetAllThreadsHardwaiting(javathreads.examples.ch06.DeadlockDetectingLock l)

        return l.hardwaitingThreads.iterator();
    
public voidlock()

        // Note: Owner can't change if current thread is owner. It is
        //       not guaranteed otherwise. Other owners can change due to
        //       condition variables.
        if (isHeldByCurrentThread()) {
            if (debugging) System.out.println("Already Own Lock");
            super.lock();
            freeIfHardwait(hardwaitingThreads, Thread.currentThread());
            return;
        }

        // Note: The wait list must be marked before it is tested because
        //       there is a race condition between lock() method calls.
        markAsHardwait(hardwaitingThreads, Thread.currentThread());
        if (canThreadWaitOnLock(Thread.currentThread(), this)) {
            if (debugging) System.out.println("Waiting For Lock");
            super.lock();
            freeIfHardwait(hardwaitingThreads, Thread.currentThread());
            if (debugging) System.out.println("Got New Lock");
        } else {
            throw new DeadlockDetectedException("DEADLOCK");
        }
    
public voidlockInterruptibly()

        lock();
    
public static voidmain(java.lang.String[] args)

        int test = 1;
	if (args.length > 0)
	    test = Integer.parseInt(args[0]);
	switch(test) {
	    case 1:
                testOne();    // 2 threads deadlocking on grabbing 2 locks
		break;
	    case 2:
        	testTwo();    // 3 threads deadlocking on grabbing 2 out of 3 locks
		break;
	    case 3:
                testThree();  // 2 threads deadlocking on 2 locks with CV wait 
		break;
	    default:
	        System.err.println("usage: java DeadlockDetectingLock [ test# ]");
	}
        delaySeconds(60);
        System.out.println("--- End Program ---");
        System.exit(0);
    
private static synchronized voidmarkAsHardwait(java.util.List l, java.lang.Thread t)


            
        if (!l.contains(t)) l.add(t);
    
public java.util.concurrent.locks.ConditionnewCondition()

        return new DeadlockDetectingCondition(this, super.newCondition());
    
private static synchronized voidregisterLock(javathreads.examples.ch06.DeadlockDetectingLock ddl)


          
        if (!deadlockLocksRegistry.contains(ddl))
             deadlockLocksRegistry.add(ddl);
    
private static voidtestOne()

         new Thread(new Runnable() {
             public void run() {
                 System.out.println("thread one grab a");
                 a.lock();
                 delaySeconds(2);
                 System.out.println("thread one grab b");
                 b.lock();
                 delaySeconds(2);
                 a.unlock(); b.unlock();
             }
         }).start();

         new Thread(new Runnable() {
             public void run() {
                 System.out.println("thread two grab b");
                 b.lock();
                 delaySeconds(2);
                 System.out.println("thread two grab a");
                 a.lock();
                 delaySeconds(2);
                 a.unlock(); b.unlock();
             }
         }).start();
    
private static voidtestThree()

         new Thread(new Runnable() {
             public void run() {
                 System.out.println("thread one grab b");
                 b.lock();
                 System.out.println("thread one grab a");
                 a.lock();
                 delaySeconds(2);
                 System.out.println("thread one waits on b");
                 awaitSeconds(wb, 10);                 
                 a.unlock(); b.unlock();
             }
         }).start();

         new Thread(new Runnable() {
             public void run() {
                 delaySeconds(1);
                 System.out.println("thread two grab b");
                 b.lock();
                 System.out.println("thread two grab a");
                 a.lock();
                 delaySeconds(10);
                 b.unlock(); c.unlock();
             }
         }).start();

    
private static voidtestTwo()

         new Thread(new Runnable() {
             public void run() {
                 System.out.println("thread one grab a");
                 a.lock();
                 delaySeconds(2);
                 System.out.println("thread one grab b");
                 b.lock();
                 delaySeconds(10);
                 a.unlock(); b.unlock();
             }
         }).start();

         new Thread(new Runnable() {
             public void run() {
                 System.out.println("thread two grab b");
                 b.lock();
                 delaySeconds(2);
                 System.out.println("thread two grab c");
                 c.lock();
                 delaySeconds(10);
                 b.unlock(); c.unlock();
             }
         }).start();

         new Thread(new Runnable() {
             public void run() {
                 System.out.println("thread three grab c");
                 c.lock();
                 delaySeconds(4);
                 System.out.println("thread three grab a");
                 a.lock();
                 delaySeconds(10);
                 c.unlock(); a.unlock();
             }
         }).start();
    
private static synchronized voidunregisterLock(javathreads.examples.ch06.DeadlockDetectingLock ddl)

        if (deadlockLocksRegistry.contains(ddl))
             deadlockLocksRegistry.remove(ddl);