Here's a simple, no frills answer. This is similar to how a read/write lock works, except that every locker has exclusive access (normally all readers proceed in parallel). Note that it does not use Semaphore
because that is almost always the wrong construct to use.
public class PrioLock {
private boolean _locked;
private boolean _priorityWaiting;
public synchronized void lock() throws InterruptedException {
while(_locked || _priorityWaiting) {
wait();
}
_locked = true;
}
public synchronized void lockPriority() throws InterruptedException {
_priorityWaiting = true;
try {
while(_locked) {
wait();
}
_locked = true;
} finally {
_priorityWaiting = false;
}
}
public synchronized void unlock() {
_locked = false;
notifyAll();
}
}
You would use it like one of the Lock types in java.util.concurrent:
Normal threads:
_prioLock.lock();
try {
// ... use resource here ...
} finally {
_prioLock.unlock();
}
"Priority" thread:
_prioLock.lockPriority();
try {
// ... use resource here ...
} finally {
_prioLock.unlock();
}
UPDATE:
Response to comment regarding "preemptive" thread interactions:
In the general sense, you cannot do that. you could build custom functionality which added "pause points" to the locked section which would allow a low priority thread to yield to a high priority thread, but that would be fraught with peril.
The only thing you could realistically do is interrupt the working thread causing it to exit the locked code block (assuming that your working code responded to interruption). This would allow a high priority thread to proceed quicker at the expense of the low priority thread losing in progress work (and you might have to implement rollback logic as well).
in order to implement this you would need to:
- record the "current thread" when locking succeeds.
- in
lockPriority()
, interrupt the "current thread" if found
- implement the logic between the
lock()
/unlock()
(low priority) calls so that:
- it responds to interruption in a reasonable time-frame
- it implements any necessary "rollback" code when interrupted
- potentially implement "retry" logic outside the
lock()
/unlock()
(low priority) calls in order to re-do any work lost when interrupted