Monday, July 11, 2011

Managing concurrent R/W access to a single resource

I have a cache which can be reloaded by client threads.
The problem is to avoid having 2 (or 20!) threads reloading it at the same time.

The solution is pretty simple:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

....

private static final Lock lock = new ReentrantLock();

public static boolean acquireLock() throws InterruptedException {
return lock.tryLock(TIMEOUT_FOR_LOCK, TimeUnit.SECONDS);
}


public static String releaseLock() {
lock.unlock();
return "OK";
}


And I have exposed these 2 functions as custom XPaths.

In my pipeline, I acquire the lock, then check again if the cache still needs to be reloaded (it might have been reloaded while trying to acquire the lock!)...

VERY important:

a) remember to release the lock, under all circumstances (i.e. do it also in error handler)
b) don't put your acquireLock in a synchronized method, otherwise a deadlock is guaranteed

There might be a case where a thread acquires the lock and then dies without executing the error handler... in this case, the lock will NEVER be released.
I still must think about this scenario, very unlikely but you never know...

No comments: