java принудительное приобретение блокировки? - PullRequest
0 голосов
/ 28 января 2020

Я работаю с несколько устаревшим механизмом рабочего процесса, он позволяет определять отдельный шаг, который выполняет код Java, но не более того.

Каждый вызов процесса рабочего процесса работает в своем собственном потоке с любыми подпроцессами, выполняющимися в одном и том же потоке синхронно.

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

Все, что я мог придумать, это получить блокировку на первом шаге подпроцесса и отпустите его на последних шагах. Если в процессе возникает исключение, его не всегда удается зафиксировать.

... s_lock = new ReentrantLock(); ...
... s_timeout = 10; ...

public static void acquireLock() throws InterruptedException {
    if( !s_lock.tryLock(s_timeout, TimeUnit.SECONDS)) {
        System.out.println("WARN: Forcing acquire of lock.");
        s_lock = new ReentrantLock();   // discard old lock and create a new one
        s_lock.lock();
    }
}

public static void releaseLock() {
    if( s_lock.isHeldByCurrentThread()) {
        s_lock.unlock();
    } else {
        System.out.println("WARN:  lock not held by thread.");          
    }
}

Должен быть лучший способ? Можно ли автоматически снять блокировку, если поток завершается?

1 Ответ

1 голос
/ 28 января 2020

Можно ли автоматически снять блокировку, если поток завершается?

Нет ни в одной из стандартных реализаций Lock. AFAIK, у них всех есть ограничение, что только поток, который получил блокировку, может снять ее. Таким образом, в вашем случае использования, когда каждый процесс рабочего процесса находится в отдельном потоке, более поздний процесс рабочего процесса не может сломать блокировку, отмененную при сбое более раннего процесса.

Но не все потеряно. Javado c для Lock.unlock() говорит следующее:

Особенности реализации

Реализация блокировки обычно накладывает ограничения на то, какой поток может снять блокировку ( как правило, только держатель замка может его снять) и может выдать (непроверенное) исключение, если ограничение нарушено. Любые ограничения и тип исключения должны быть задокументированы этой реализацией Lock.

Обратите внимание, что ограничение не является обязательным. Таким образом, вы могли бы написать свою собственную реализацию Lock без ограничения на unlock().

Более того, если вы можете гарантировать, что потоки, которые запускают процессы рабочих процессов, не будут повторно использоваться, есть схема, которая может быть использован для безопасного взлома блокировки .

  • Когда поток получает одну из этих блокировок, он передает кортеж, состоящий из текущего объекта Thread и объекта заблокировать отдельную нить монитора блокировки.

  • Поток монитора блокировки периодически сканирует кортежи на наличие всех ожидающих блокировок.

  • Для каждого кортежа монитор вызывает Thread.isAlive(), чтобы проверить, работает ли еще поток, удерживающий блокировку. Когда поток с блокировкой больше не работает, поток монитора разблокирует блокировку и удаляет кортеж.

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


Реализация пользовательского класса Lock и монитор блокировки не будут тривиальными ...


By Кстати, ваш текущий подход имеет недостатки:

  • Если время ожидания невелико, существует риск того, что вы сломаете блокировку, пока исходный процесс рабочего процесса все еще выполняется.

  • Если время ожидания велико, сбойный процесс может слишком долго блокировать другие процессы.

  • Не существует «промежуточной» точки, в которой Вы получаете гарантированные надежные замки и отзывчивость.

...