Добрый день!
Прошу помощи в оценке моего решения. Тестирование показывает корректный возврат для обоих вариантов порядка блокировки метода someMethodWithSynchronizedBlocks.
Но валидатор не пропускает по второму пункту...
Что подправить?
Алгоритм следующий:
- Запускаем первую демон нить для блокировки монитора объекта о1. После блокировки нить сразу засыпает на 2 секунды.
- даём 10 миллисекунд на запуск
- запускаем вторую демон нить для вызова метода someMethodWithSynchronizedBlocks. Нить должна заблокироваться либо по о1, либо по о2. Если нить блокирует монитор о2, значит он идёт первым в порядке блокировки метода someMethodWithSynchronizedBlocks. Значит мы должны вернуть false, если о2 не блокируется, то возвращаем true.
- проверяем все заблокированные мониторы объектов у каждой нити. Сверяем по хэшкоду с объектом о2, если есть совпадение, то значит вторая нить заблокировала о2 -> возвращаем false. Иначе true.
package com.javarush.task.task27.task2707;
/*
Определяем порядок захвата монитора
*/
import java.lang.management.ManagementFactory;
import java.lang.management.MonitorInfo;
import java.lang.management.ThreadInfo;
import java.sql.SQLOutput;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Solution {
public void someMethodWithSynchronizedBlocks(Object obj1, Object obj2) {
synchronized (obj1) {
synchronized (obj2) {
System.out.println(obj1 + " " + obj2);
}
}
}
public static boolean isLockOrderNormal(final Solution solution, final Object o1, final Object o2) throws Exception {
// запускаем первую демон нить, которая блокирует o1 на 2 секунды
Thread thread = new Thread(){
@Override
public void run() {
synchronized (o1){
try {
sleep(2000);
} catch (InterruptedException ignore) {
}
}//end synch which blocks o1 for 2 seconds
}//end run
};
thread.setDaemon(true);
thread.start();
Thread.currentThread().sleep(10);
// запускаем вторую демон нить, которая пытается вызвать метод someMethodWithSynchronizedBlocks и блокируется
// либо на o1, либо на o2
Thread threadForMethodCall = new Thread(){
@Override
public void run() {
solution.someMethodWithSynchronizedBlocks(o1,o2);
}//end run
};
threadForMethodCall.setDaemon(true);
threadForMethodCall.start();
Thread.currentThread().sleep(10);
// находим информацию по всем заблокированным мониторам. Сверяем по хэш коду заблокирован ли объект о2
// если он заблокирован, то порядок блокировки в методе someMethodWithSynchronizedBlocks начинается с о2
// значит надо вернуть false, если монитор о2 не заблокирован, то возвращаем true
try {
ThreadInfo[] mass = ManagementFactory.getThreadMXBean().dumpAllThreads(true, true);
for (ThreadInfo ti : mass) { // перебираем массив всех нитей
for (MonitorInfo o : ti.getLockedMonitors()) { // перебираем все заблокированные мониторы у каждой нити
if (o.getIdentityHashCode() == o2.hashCode()) {
return false;
}//end if
}// end inner for
}// end for
}catch(Exception ignore){}
return true;
} // end isLockOrderNormal
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));
//System.out.println("main is ended");
}
}
/*
Определяем порядок захвата монитора
Реализуй логику метода isLockOrderNormal, который должен определять:
соответствует ли порядок synchronized блоков в методе someMethodWithSynchronizedBlocks -
порядку передаваемых в него аргументов.
В случае, если сначала происходит синхронизация по o1, а потом по o2, метод должен вернуть true.
Если наоборот - false.
Требования:
1. Метод isLockOrderNormal должен возвращать true в случае, если синхронизация в
методе someMethodWithSynchronizedBlocks происходит сначала по объекту o1, а потом по o2.
2. Метод isLockOrderNormal должен возвращать false в случае, если синхронизация в
методе someMethodWithSynchronizedBlocks происходит сначала по объекту o2, а потом по o1.
3. Метод isLockOrderNormal НЕ должен быть приватным.
4. Класс Solution НЕ должен быть объявлен с модификатором final.
*/