Суть задания такова:
1. Метод isLockOrderNormal должен возвращать true в случае, если синхронизация в методе someMethodWithSynchronizedBlocks происходит сначала по объекту o1, а потом по o2.
2. Метод isLockOrderNormal должен возвращать false в случае, если синхронизация в методе someMethodWithSynchronizedBlocks происходит сначала по объекту o2, а потом по o1.
Так вот задание я выполнил, его приняло, но если в методе someMethodWithSynchronizedBlocks написать synchronized блоки именно в таком порядке, то выдаёт false как положено, но программа не завершает работу. Как это правильно переписать что бы метод isLockOrderNormal выполнял свою функцию и не зависал работу всей программы и завершался в любом случае? Менять можно только тело метода isLockOrderNormal.
public class Solution {
public void someMethodWithSynchronizedBlocks(Object obj1, Object obj2) {
synchronized (obj2) {
synchronized (obj1) {
// System.out.println(obj1 + " " + obj2);
}
}
}
public static boolean isLockOrderNormal(final Solution solution, final Object o1, final Object o2) throws Exception {
//создаём 2 потока.
// В первом потоке берём мьютекс "о1" и ждём что бы дать возможность
// другому потоку попробовать войти в свой synchronized блок.
// Потом занимаем мьютекс "о2" что бы в случае когда второй блок займёт
//свой первый мьютекс возник DeadLock
Thread t1 = new Thread(() -> {
synchronized (o1) {
try {
o1.wait();
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (o2) { }
}
});
//Второй поток просто вызывает нужный метод где и будет занимать
//соответсвующие мьютексы
Thread t2 = new Thread(() -> solution.someMethodWithSynchronizedBlocks(o1, o2));
//Обеспечиваем запуск нитей так что бы первая нить в любом случае
//успела занять свой первый мьютекс
t1.start();
Thread.sleep(5);
t2.start();
//Даём время нитям друг-друга заблокировать если параметры
//переданы не в нужном порядке или отработать им до конца.
Thread.sleep(2050);
//Если DeadLock не произошёл, то вторая нить успеет закончить работу.
//Если DeadLock возник, то вторая нить будет заблокированаю.
//Соответственно обрабатываем оба случая
if (t2.getState() != Thread.State.BLOCKED) {
return true;
} else {
//Программа зависает даже если подгадать момент что бы
//первая нить прерывалась.
t1.interrupt();
t2.interrupt();
return false;
}
// System.out.println("State t1: " + t1.getState());
// System.out.println("State t2: " + t2.getState());
// return false;
}
public static void main(String[] args) throws Exception {
final Solution solution = new Solution();
final Object o1 = new Object();
final Object o2 = new Object();
System.out.println(isLockOrderNormal(solution, o1, o2));
}