ReentrantLock :测试死锁 : 死锁 « 线程 « Java

En
Java
1. 图形用户界面
2. 三维图形动画
3. 高级图形
4. 蚂蚁编译
5. Apache类库
6. 统计图
7. 
8. 集合数据结构
9. 数据类型
10. 数据库JDBC
11. 设计模式
12. 开发相关类
13. EJB3
14. 电子邮件
15. 事件
16. 文件输入输出
17. 游戏
18. 泛型
19. GWT
20. Hibernate
21. 本地化
22. J2EE平台
23. 基于J2ME
24. JDK-6
25. JNDI的LDAP
26. JPA
27. JSP技术
28. JSTL
29. 语言基础知识
30. 网络协议
31. PDF格式RTF格式
32. 映射
33. 常规表达式
34. 脚本
35. 安全
36. Servlets
37. Spring
38. Swing组件
39. 图形用户界面
40. SWT-JFace-Eclipse
41. 线程
42. 应用程序
43. Velocity
44. Web服务SOA
45. 可扩展标记语言
Java 教程
Java » 线程 » 死锁屏幕截图 
ReentrantLock :测试死锁
ReentrantLock :测试死锁

/*
Java Threads, 3rd Edition
By Scott Oaks, Henry Wong
3rd Edition September 2004 
ISBN: 0-596-00782-5

*/

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

// This is a very slow implementation of a ReentrantLock class and is not for
//   everyday usage. The purpose of this class is to test for deadlocks. The
// lock()
//   method now throws a DeadlockDetectedException, if a deadlock occurs. This
//   Alternate version has some production properties, including faster
//   deadlock check, full implementation of all lock methods, and configurable
//   options.
public class AlternateDeadlockDetectingLock extends ReentrantLock {
  // List of deadlock detecting locks.
  // This array is not thread safe, and must be externally synchronized
  //    by the class lock. Hence, it should only be called by static
  //    methods.
  private static List deadlockLocksRegistry = new ArrayList();

  private static synchronized void registerLock(
      AlternateDeadlockDetectingLock ddl) {
    if (!deadlockLocksRegistry.contains(ddl))
      deadlockLocksRegistry.add(ddl);
  }

  private static synchronized void unregisterLock(
      AlternateDeadlockDetectingLock ddl) {
    if (deadlockLocksRegistry.contains(ddl))
      deadlockLocksRegistry.remove(ddl);
  }

  // List of threads hard waiting for this lock.
  // This array is not thread safe, and must be externally synchronized
  //    by the class lock. Hence, it should only be called by static
  //    methods.
  private List hardwaitingThreads = new ArrayList();

  private static synchronized void markAsHardwait(List l, Thread t) {
    if (!l.contains(t))
      l.add(t);
  }

  private static synchronized void freeIfHardwait(List l, Thread t) {
    if (l.contains(t))
      l.remove(t);
  }

  //
  // Deadlock checking methods
  //
  // Given a thread, return all locks that are already owned
  // Must own class lock prior to calling this method
  private static Iterator getAllLocksOwned(Thread t) {
    AlternateDeadlockDetectingLock current;
    ArrayList results = new ArrayList();

    Iterator itr = deadlockLocksRegistry.iterator();
    while (itr.hasNext()) {
      current = (AlternateDeadlockDetectingLockitr.next();
      if (current.getOwner() == t)
        results.add(current);
    }
    return results.iterator();
  }

  // Given a lock, return all threads that are hard waiting for the lock
  // Must own class lock prior to calling this method
  private static Iterator getAllThreadsHardwaiting(
      AlternateDeadlockDetectingLock l) {
    return l.hardwaitingThreads.iterator();
  }

  // Check to see if a thread can perform a hard wait on a lock
  // Must call synchronized version only...
  private static boolean canThreadWaitOnLock0(Thread t,
      AlternateDeadlockDetectingLock l) {
    Iterator locksOwned = getAllLocksOwned(t);
    while (locksOwned.hasNext()) {
      AlternateDeadlockDetectingLock current = (AlternateDeadlockDetectingLocklocksOwned
          .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 = (ThreadwaitingThreads.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 synchronized boolean canThreadWaitOnLock(Thread t,
      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);
  }

  // Options: variable to control behavior
  //    FastFail: if set true, deadlock exception will thrown for every call
  // after
  //              first exception is detected
  //     CleanUp: if set true, lock will cleanup deadlock condition -- allowing
  //              for continued operation after failure. FastFail must be off.
  //    HWSWTime: # of seconds before a Softwait is to be considered as a
  // hardwait.
  //              Default is 60 seconds.
  private static boolean DDLFastFail = false;

  private static boolean DDLCleanUp = false;

  private static int DDLHWSWTime = 60;

  // Core Constructors
  //
  public AlternateDeadlockDetectingLock() {
    this(false, false);
  }

  public AlternateDeadlockDetectingLock(boolean fair) {
    this(fair, false);
  }

  private boolean debugging;

  public AlternateDeadlockDetectingLock(boolean fair, boolean debug) {
    super(fair);
    debugging = debug;
    registerLock(this);
  }

  private static boolean DDLdeadlockDETECTED = false;

  //
  // Core Methods
  //
  public void lock() {
    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");
    }
  }

  //
  // Note: It is debatable whether this is a hard or soft wait. Even if
  //       interruption is common, we don't know if the interrupting thread
  //       is also involved in the deadlock. In this alternate version, it
  //       will be treated as a hard wait.
  public void lockInterruptibly() throws InterruptedException {
    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");
    }
  }

  //
  // Note: It is debatable where is the point between a hard wait and a
  //      soft wait. Is it still a soft wait, if the timeout is large? As
  //      compromise, it is to be considered a hardwait if the timeout
  //      is larger than a specified time. Developers should modify this method
  //      as needed.
  public boolean tryLock(long time, TimeUnit unit)
      throws InterruptedException {
    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");
    }
  }

  // Note 1: Deadlocks are possible with any hard wait -- this includes
  //      the reacquitition of the lock upon return from an await() method.
  //      As such, condition variables will mark for the future hard
  //      wait, prior to releasing the lock.
  // Note 2: There is no need to check for deadlock on this end because
  //      a deadlock can be created whether the condition variable owns the
  //      lock or is reacquiring it. Since we are marking *before* giving
  //      up ownership, the deadlock will be detected on the lock() side
  //      first. It is not possible to create a new deadlock just by releasing
  //      locks.
  public class DeadlockDetectingCondition implements Condition {
    Condition embedded;

    protected DeadlockDetectingCondition(ReentrantLock lock,
        Condition embedded) {
      this.embedded = embedded;
    }

    // Note: The algorithm can detect a deadlock condition if the thead is
    //    either waiting for or already owns the lock, or both. This is why
    //    we have to mark for waiting *before* giving up the lock.
    public void await() throws InterruptedException {
      try {
        markAsHardwait(hardwaitingThreads, Thread.currentThread());
        embedded.await();
      finally {
        freeIfHardwait(hardwaitingThreads, Thread.currentThread());
      }
    }

    public void awaitUninterruptibly() {
      markAsHardwait(hardwaitingThreads, Thread.currentThread());
      embedded.awaitUninterruptibly();
      freeIfHardwait(hardwaitingThreads, Thread.currentThread());
    }

    public long awaitNanos(long nanosTimeoutthrows InterruptedException {
      try {
        markAsHardwait(hardwaitingThreads, Thread.currentThread());
        return embedded.awaitNanos(nanosTimeout);
      finally {
        freeIfHardwait(hardwaitingThreads, Thread.currentThread());
      }
    }

    public boolean await(long time, TimeUnit unit)
        throws InterruptedException {
      try {
        markAsHardwait(hardwaitingThreads, Thread.currentThread());
        return embedded.await(time, unit);
      finally {
        freeIfHardwait(hardwaitingThreads, Thread.currentThread());
      }
    }

    public boolean awaitUntil(Date deadlinethrows InterruptedException {
      try {
        markAsHardwait(hardwaitingThreads, Thread.currentThread());
        return embedded.awaitUntil(deadline);
      finally {
        freeIfHardwait(hardwaitingThreads, Thread.currentThread());
      }
    }

    public void signal() {
      embedded.signal();
    }

    public void signalAll() {
      embedded.signalAll();
    }
  }

  // Return a condition variable that support detection of deadlocks
  public Condition newCondition() {
    return new DeadlockDetectingCondition(this, super.newCondition());
  }

  //
  // Testing routines here
  //
  // These are very simple tests -- more tests will have to be written
  private static Lock a = new AlternateDeadlockDetectingLock(false, true);

  private static Lock b = new AlternateDeadlockDetectingLock(false, true);

  private static Lock c = new AlternateDeadlockDetectingLock(false, true);

  private static Condition wa = a.newCondition();

  private static Condition wb = b.newCondition();

  private static Condition wc = c.newCondition();

  private static void delaySeconds(int seconds) {
    try {
      Thread.sleep(seconds * 1000);
    catch (InterruptedException ex) {
    }
  }

  private static void awaitSeconds(Condition c, int seconds) {
    try {
      c.await(seconds, TimeUnit.SECONDS);
    catch (InterruptedException ex) {
    }
  }

  private static void testOne() {
    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 void testTwo() {
    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 void testThree() {
    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();

  }

  public static void main(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);
  }
}class DeadlockDetectedException extends RuntimeException {

    public DeadlockDetectedException(String s) {
        super(s);
    }
}



           
       
Related examples in the same category
1. 演示如何死锁可以隐藏在程序里
2. 另一个死锁演示
3. 死锁检测死锁检测
4. 用中断方法摆脱阻塞线程。用中断方法摆脱阻塞线程。
www.java2java.com | Contact Us
Copyright 2010 - 2030 Java Source and Support. All rights reserved.
All other trademarks are property of their respective owners.