Штампованная блокировка Java 8: почему этот фрагмент кода не приводит к взаимоблокировке?

Пытаясь понять оптимистическую блокировку в Java 8, я наткнулся на приведенный ниже фрагмент кода. Исходный блог здесь .

Как объясняется в блоге, этот фрагмент кода пытается преобразовать блокировку чтения в блокировку записи. Код запрашивает явную блокировку записи, если преобразование блокировки чтения в блокировку записи не удалось.

Это меня озадачивает Как можно ожидать, что явная блокировка записи будет предоставлена, когда родительский поток уже удерживает блокировку чтения? Не похоже, что блокировка чтения снимается в любой момент до того, как принудительно запрошена блокировка записи. Насколько я понимаю, поток будет бесконечно ждать блокировки записи, поскольку блокировка чтения никогда не снимается, создавая взаимоблокировку.

Почему это не приводит к тупиковой ситуации здесь?

ExecutorService executor = Executors.newFixedThreadPool(2);
StampedLock lock = new StampedLock();

executor.submit(() -> {
    long stamp = lock.readLock();
    try {
        if (count == 0) {
            stamp = lock.tryConvertToWriteLock(stamp);
            if (stamp == 0L) {
                System.out.println("Could not convert to write lock");
                stamp = lock.writeLock();
            }
            count = 23;
        }
        System.out.println(count);
    } finally {
        lock.unlock(stamp);
    }
});

stop(executor);

Заранее спасибо!


person Abdul23    schedule 13.01.2021    source источник
comment
На самом деле это больше теоретический вопрос. Почему блокировка записи предоставляется, когда поток уже удерживает блокировку чтения, учитывая, что Stampedlocks не допускает повторного входа? У меня нет проблем с этим фрагментом кода. Просто пытаюсь понять аргументацию, объясненную в блоге.   -  person Abdul23    schedule 13.01.2021
comment
Всем читателям: вот та же проблема, выделенная по-разному и с ответом stackoverflow.com/q/49216525/3835632   -  person Abdul23    schedule 13.01.2021


Ответы (1)


Это помогает? Из API для tryConvertToWriteLock

Если состояние блокировки соответствует заданному штампу, атомарно выполняет одно из следующих действий. Если штамп представляет удержание блокировки записи, возвращает ее. Или, если блокировка чтения, если доступна блокировка записи, снимает блокировку чтения и возвращает отметку записи. Или, если чтение оптимистично, возвращает отметку записи, только если она доступна немедленно. Этот метод возвращает ноль во всех остальных случаях.

person WJS    schedule 13.01.2021
comment
Итак, здесь, в случае, который я подчеркиваю, блокировка записи недоступна. Таким образом, это возвращает нулевую метку времени. Затем код должен запросить блокировку записи. Насколько я понимаю, блокировка записи не будет предоставлена, если не будет снята блокировка чтения, удерживаемая тем же потоком, что приводит к взаимоблокировке. Единственная возможность, которую я могу себе представить, это то, что tryConvertToWriteLock вызывает снятие блокировки чтения при ее вызове, даже если преобразование не удалось. - person Abdul23; 13.01.2021
comment
Вот ответ stackoverflow.com/a/49216624/3835632 - person Abdul23; 13.01.2021