java如何确定是否存在明显的死锁?

时间:2014-11-20 16:05:14

标签: java concurrency

我有一个测试单元来测量电梯控制器等级的正确性,它可以模拟进出人员和提升门的开启和关闭。

我的问题是,每次超出我的10次测试时,一两次会引发以下失败:

java.lang.IllegalStateException: Apparent deadlock
thread 1 WAITING
  java.lang.Object.wait(Native Method)
  java.lang.Object.wait(Object.java:485)
  lift.MyLiftController.callLift(MyLiftController.java:23)
  lift.MyLiftControllerMultithreadedTest1.thread1(MyLiftControllerMultithreadedTest1.java:29)
  sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
  sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
  java.lang.reflect.Method.invoke(Method.java:597)
  edu.umd.cs.mtc.TestFramework$2.run(TestFramework.java:592)
  java.lang.Thread.run(Thread.java:695)

    at edu.umd.cs.mtc.TestFramework$1.run(TestFramework.java:483)

有时候会说这样的话:

Exception in thread "thread 2" java.lang.AssertionError: thread 2 killed by thread 1

因此我的问题是:

  

Java何时确定进程是否明显陷入僵局?

以下是相关代码的片段:

TestLifeMultiple1.java

这是测试,运行100次

@Test
    public void testLiftMultiple1() throws Throwable {
        System.out.println("TEST 1: MULTIPLE TIMES TO DETECT INTERMITTENT FAILURES.");
        TestFramework.runManyTimes( new MyLiftControllerMultithreadedTest1(),100);
    }

MyLiftControllerMultithreadedTest2.java

这是测试的实际内容

// Person thread 1.
public void thread1() throws InterruptedException {

    // Person calls the lift to floor 4, going UP.
    lift_controller.callLift(4, LiftController.Direction.UP);

    // Person thread should only be here when tick 2 has occurred ...
    // since this indicates the lift thread has actually opened the doors.
    assertTick(2);
}

// Person thread 2.
public void thread2() throws InterruptedException {
  // same as thread 1
}

public void thread3() throws InterruptedException {

    // Force Lift thread to wait until person threads are blocked,
    // and the different person threads have called the lift.
    waitForTick(1);

    for (int level = 0; level < 4; level++) {
        // Level 0,1,2 and 3 ... should not open doors ... hence return False.
        Assert.assertFalse(lift_controller.liftAtFloor(level, LiftController.Direction.UP));
    }

    // Level 4 ... should open doors ... hence return True.
    Assert.assertTrue(lift_controller.liftAtFloor(4, LiftController.Direction.UP));

    //.....similar stuff

    // Open the doors even if incorrect previous assertion ...
    lift_controller.doorsOpen(7);
    lift_controller.doorsClosed(7);
}

MyLiftController.java

/* Interface for People */
public synchronized void callLift(int floor, Direction direction) throws InterruptedException {
    numOfPplAtFlrInDir[floor][direction2Int(direction)] ++;

    // Person can only enter when they are on the right floor towards right direction, 
    while (floor != currentFloor || direction != currentDirection){
        wait(); 
    }

    numOfPplAtFlrInDir[floor][direction2Int(direction)] --;
    if (numOfPplAtFlrInDir[floor][direction2Int(direction)] == 0) {
        notify();
    }

    debug("Someone has entered "+floor);
}

以下代码也在MyLiftController中,它用于设置currentFloor和currentDirection。但正如你所看到的,在线程3上调用:

/* Interface for Lifts */
public synchronized boolean liftAtFloor(int floor, Direction direction) {
        currentFloor = floor;
        currentDirection = direction;

        //if there are people who will get in or out at floor X in direction Y
        if (numOfPplAtFlrInDir[floor][direction2Int(direction)]!=0 || numOfPplAtFlr[floor]!=0){
            return true;
        }
        return false;
}

// door waits indefinitely until all people exit or enter
public synchronized void doorsOpen(int floor) throws InterruptedException {

    // ask everyone to take action and wait for them to finish
    notifyAll();
    while (numOfPplAtFlrInDir[floor][direction2Int(currentDirection)]!=0 && numOfPplAtFlr[floor]!=0){
        wait(); 
    }

}

// while door is closed, no one is allowed to enter again 
// (they will be waiting)
public void doorsClosed(int floor) {
    debug("door is closed at "+floor);
    //next round will start
}

我想知道的是为什么,我的测试随机失败。 Java如何确定是否存在明显的死锁?非常感谢你!

编辑:

行动,我没有发布我的门打开和关闭功能。基本上,waitO最终都会通过doorsOpen函数通知。这会让它变得更清楚吗?

1 个答案:

答案 0 :(得分:1)

决定这一点的不是Java。这是您正在使用的MultithreadedTC框架。

至于你的错误,当你的两个主题已经转到wait()时,他们就不再有notify()了。你的线程3可能正在做,但现在它只是设置一些变量而不是打扰通知任何等待的线程。