FileDocCategorySizeDatePackage
AlternateDeadlockDetectingLock.javaAPI DocExample18570Sat May 29 22:23:38 BST 2004javathreads.examples.ch06

AlternateDeadlockDetectingLock

public class AlternateDeadlockDetectingLock extends ReentrantLock

Fields Summary
private static List
deadlockLocksRegistry
private List
hardwaitingThreads
private static boolean
DDLFastFail
private static boolean
DDLCleanUp
private static int
DDLHWSWTime
private boolean
debugging
private static boolean
DDLdeadlockDETECTED
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 AlternateDeadlockDetectingLock(boolean fair)

        this(fair, false);
    
public AlternateDeadlockDetectingLock(boolean fair, boolean debug)

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


    // Core Constructors
    //
      
        this(false, 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.AlternateDeadlockDetectingLock l)

        // Skip check if there is no owner
        // There is a race condition is the owner is null. However, it doesn't matter.
        //     Testing for no owner ensures none of the threads in the thread wait
        //     tree will grab it later -- as all locks in the tree are owned.
        if (l.getOwner() == null) {
            return true;
        }
        return canThreadWaitOnLock0(t,l);
    
private static booleancanThreadWaitOnLock0(java.lang.Thread t, javathreads.examples.ch06.AlternateDeadlockDetectingLock l)

        Iterator locksOwned = getAllLocksOwned(t);
        while (locksOwned.hasNext()) {
            AlternateDeadlockDetectingLock current = (AlternateDeadlockDetectingLock) 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 (!canThreadWaitOnLock0(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)

        AlternateDeadlockDetectingLock current;
        ArrayList results = new ArrayList();

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

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

    //
    // Core Methods
    //
       
        if (DDLFastFail && DDLdeadlockDETECTED) {
            throw new DeadlockDetectedException("EARILER DEADLOCK DETECTED");
        }

        // 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 {
            DDLdeadlockDETECTED = true;
            if (DDLCleanUp) freeIfHardwait(hardwaitingThreads, Thread.currentThread());
            throw new DeadlockDetectedException("DEADLOCK DETECTED");
        }
    
public voidlockInterruptibly()

        if (DDLFastFail && DDLdeadlockDETECTED) {
            throw new DeadlockDetectedException("EARILER DEADLOCK DETECTED");
        }

        // 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");
            try {
                super.lockInterruptibly();
            } finally {
                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");
            try {
                super.lockInterruptibly();
            } finally {
                freeIfHardwait(hardwaitingThreads, Thread.currentThread());
            }
            if (debugging) System.out.println("Got New Lock");
        } else {
            DDLdeadlockDETECTED = true;
            if (DDLCleanUp) freeIfHardwait(hardwaitingThreads, Thread.currentThread());
            throw new DeadlockDetectedException("DEADLOCK DETECTED");
        }
    
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.AlternateDeadlockDetectingLock 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();
    
public booleantryLock(long time, java.util.concurrent.TimeUnit unit)

        if (DDLFastFail && DDLdeadlockDETECTED) {
            throw new DeadlockDetectedException("EARILER DEADLOCK DETECTED");
        }

        // Perform operation as a soft wait
        if (unit.toSeconds(time) < DDLHWSWTime) {
            return super.tryLock(time, unit);
        }

        // 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");
            try {
                return super.tryLock(time, unit);
            } finally {
                freeIfHardwait(hardwaitingThreads, Thread.currentThread());
            }
        }

        // 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");
            try {
                return super.tryLock(time, unit);
            } finally {
                freeIfHardwait(hardwaitingThreads, Thread.currentThread());
                if (debugging) System.out.println("Got New Lock");
            }
        } else {
            DDLdeadlockDETECTED = true;
            if (DDLCleanUp) freeIfHardwait(hardwaitingThreads, Thread.currentThread());
            throw new DeadlockDetectedException("DEADLOCK DETECTED");
        }
    
private static synchronized voidunregisterLock(javathreads.examples.ch06.AlternateDeadlockDetectingLock ddl)

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