Два потока должны сначала захватить разные мониторы и дождаться друг друга на барьере, удерживая их. Затем каждый запрашивает монитор другого: образуется цикл ожидания.
Создание примера гарантированного взаимоблокировки
Два потока должны сначала захватить разные мониторы и дождаться друг друга на барьере, удерживая их. Затем каждый запрашивает монитор другого: образуется цикл ожидания.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Напишите программу, которая воспроизводит ситуацию, в которой несколько потоков неизбежно попадают в взаимную блокировку, тем самым демонстрируя гарантированный deadlock.
Ответ
Два потока должны сначала захватить разные мониторы и дождаться друг друга на барьере, удерживая их. Затем каждый запрашивает монитор другого: образуется цикл ожидания.
Object a = new Object(), b = new Object();
var barrier = new java.util.concurrent.CyclicBarrier(2);
Runnable first = () -> lockBoth(a, b, barrier);
Runnable second = () -> lockBoth(b, a, barrier);
new Thread(first).start();
new Thread(second).start();
Вспомогательный метод:
static void lockBoth(Object first, Object second,
java.util.concurrent.CyclicBarrier barrier) {
synchronized (first) {
try { barrier.await(); }
catch (Exception e) { throw new RuntimeException(e); }
synchronized (second) { System.out.println("Unreachable"); }
}
}
При нормальном запуске обоих потоков без прерывания барьера deadlock не зависит от sleep и случайного тайминга. Это намеренно зависающий учебный пример, запускаемый только изолированно. Исправление — единый порядок захвата a, затем b.