Одного обратного порядка мониторов недостаточно для гарантии: один поток может успеть захватить оба. Барьер после первого захвата заставит оба потока удерживать по одному монитору.
Непременно вызывающий deadlock
Одного обратного порядка мониторов недостаточно для гарантии: один поток может успеть захватить оба. Барьер после первого захвата заставит оба потока удерживать по одному монитору.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Необходимо реализовать класс, в котором гарантированно возникает взаимная блокировка потоков. Для демонстрации следует задействовать два потока и два синхронизируемых объекта. Каждый поток должен захватывать мониторы в разном порядке, что приводит к безвыходной ситуации deadlock.
public class Deadlock {
private final Object monitorA = new Object();
private final Object monitorB = new Object();
public void run1() {
// ...
}
public void run2() {
// ...
}
public static void main(String[] args) {
// ...
}
}
Ответ
Одного обратного порядка мониторов недостаточно для гарантии: один поток может успеть захватить оба. Барьер после первого захвата заставит оба потока удерживать по одному монитору.
public class Deadlock {
private final Object monitorA = new Object(), monitorB = new Object();
private final java.util.concurrent.CyclicBarrier barrier =
new java.util.concurrent.CyclicBarrier(2);
public void run1() { lock(monitorA, monitorB); }
public void run2() { lock(monitorB, monitorA); }
private void lock(Object first, Object second) {
synchronized (first) {
try { barrier.await(); }
catch (Exception e) { throw new RuntimeException(e); }
synchronized (second) { System.out.println("Not reached"); }
}
}
public static void main(String[] args) {
Deadlock demo = new Deadlock();
new Thread(demo::run1).start();
new Thread(demo::run2).start();
}
}
Без внешнего прерывания оба потока зависнут в цикле ожидания. Учебный пример запускают изолированно и завершают процесс отдельно. Для предотвращения deadlock захватывайте мониторы в едином порядке.