How to avoid concurrent execution of a time-consuming task without blocking?
- by Diego V
I want to efficiently avoid concurrent execution of a time-consuming task in a heavily multi-threaded environment without making threads wait for a lock when another thread is already running the task. Instead, in that scenario, I want them to gracefully fail (i.e. skip its attempt to execute the task) as fast as possible.
To illustrate the idea considerer this unsafe (has race condition!) code:
private static boolean running = false;
public void launchExpensiveTask() {
if (running) return; // Do nothing
running = true;
try {
runExpensiveTask();
} finally {
running = false;
}
}
I though about using a variation of Double-Checked Locking (consider that running is a primitive 32-bit field, hence atomic, it could work fine even for Java below 5 without the need of volatile). It could look like this:
private static boolean running = false;
public void launchExpensiveTask() {
if (running) return; // Do nothing
synchronized (ThisClass.class) {
if (running) return;
running = true;
try {
runExpensiveTask();
} finally {
running = false;
}
}
}
Maybe I should also use a local copy of the field as well (not sure now, please tell me).
But then I realized that anyway I will end with an inner synchronization block, that still could hold a thread with the right timing at monitor entrance until the original executor leaves the critical section (I know the odds usually are minimal but in this case we are thinking in several threads competing for this long-running resource).
So, could you think in a better approach?