Atomically grab multiple locks

Viewed 234

Assume we have to undertake a transfer between any 2 accounts(among hunders out there) as part of a transaction.
And there would be multiple similar transactions running concurrently in a typical multi-threaded environment.
Usual convention would be as below(maintaining the lock order as per a pre-designed convention):

lock account A
lock account B
transfer(A,B)
release B
release A

Is there any way to attempt the locks and release as an atomic operation?

3 Answers

You can try to use the following code. Note: it only work for two locks and I'm unsure how to make it scale to more locks. The idea is that you take the first lock and you try to take the second one. If it fails, we know that 1 lock is free right now, but the other is busy. Thus we release the first lock and you invert them, so we will lock on the one that was busy and try to take the one that (WAS!) free, if it is still free. Rinse and repeat. There is a statistically impossibility that this code will go in StackOverflow, I think handling it and giving an error is better than making it loop, since it would be a signal that something somewhere is going very wrong.

public static void takeBoth(ReentrantLock l1,ReentrantLock l2) {
    l1.lock();
    if(l2.tryLock()) {return;}
    l1.unlock();
    try{takeBoth(l2,l1);}
    catch(StackOverflowError e) {throw new Error("??");}
  }
  public static void releaseBoth(ReentrantLock l1,ReentrantLock l2){
    if(!l1.isHeldByCurrentThread()) {l1.unlock();}//this will fail: IllegarMonitorState exception
    l2.unlock();//this may fail, in that case we did not touch l1.
    l1.unlock();    
    }
Related