Извините, если название - скороговорка, но я не смог бы сформулировать это лучше, потому что это именно то, что я хочу сделать.
У меня есть этот метод / код:
// No need fairness (false) the first to get it is good to go
private final Lock TEST = new ReentrantLock(false)
public methodCalledByMultipleThreads() {
// 1st code section - no concurrency problems
// regardless of what happen in section 2 a thread that just called
// this function should always be able to run section 1
// 2nd code section begin
if (rare_condition && TEST.tryLocking()) {
// check again to avoid limit cases where "rare_condition" value
// is invalidated by another thread (who ran "important stuffs")
// and just released/unlock TEST with "TEST.unlock();"
if (check_rare_condition_again) {
// ##### do "important stuffs" #####
// release lock
TEST.unlock();
}
}
TEST.waitUntilUnlocked(); // this is what I actually would like to do
// ##### do other stuffs #####
}
Конечно, «waitUntilUnlocked» не должен блокировать «TEST», когда ожидание закончено. Я пытался получить желаемое поведение с помощью хакерского использования семафора ... что очень плохо, семафоры не созданы для этого и в этом случае также приводят к накладным расходам (внутренний счет разрешений ничего не учитывает ... просто необычный замок):
private final Lock TEST = new ReentrantLock(false)
// absurd high value (Integer.MAX_VALUE) for permits, to allow "virtually"
// infinite threads to works with this code
private final Semaphore SEM = new Semaphore(Integer.MAX_VALUE, true);
public methodCalledByMultipleThreads() {
// 1st code section
// 2nd code section begin
if (rare_condition && TEST.tryLocking()) {
if (check_rare_condition_again) {
// waits to gets all permits
SEM.acquireUninterruptibly(Integer.MAX_VALUE);
// ##### do important stuffs #####
// release all permits
SEM.release(Integer.MAX_VALUE);
// release lock
TEST.unlock();
}
}
// ask one permit
SEM.acquireUninterruptibly();
// ##### do other stuffs #####
// release one permit
SEM.release();
}
Вышеупомянутое решение "работает" (к счастью, в реальной реализации код достаточно медленный, чтобы не вызывать крайние случаи ... на данный момент), но теоретически неверен, так как "SEM.release (Integer.MAX_VALUE);" и "TEST.unlock ();" должно быть одно.
Как я могу получить такое поведение без этого уродливого взлома?