我有一个测试单元来测量电梯控制器等级的正确性,它可以模拟进出人员和提升门的开启和关闭。
我的问题是,每次超出我的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何时确定进程是否明显陷入僵局?
以下是相关代码的片段:
@Test
public void testLiftMultiple1() throws Throwable {
System.out.println("TEST 1: MULTIPLE TIMES TO DETECT INTERMITTENT FAILURES.");
TestFramework.runManyTimes( new MyLiftControllerMultithreadedTest1(),100);
}
// 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);
}
/* 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函数通知。这会让它变得更清楚吗?
答案 0 :(得分:1)
决定这一点的不是Java。这是您正在使用的MultithreadedTC框架。
至于你的错误,当你的两个主题已经转到wait()
时,他们就不再有notify()
了。你的线程3可能正在做,但现在它只是设置一些变量而不是打扰通知任何等待的线程。