I am wondering what are the alternative ways to avoid deadlock in the following example. The following example is a typical bank account transferring deadlock problem. What
There are three requirements you must satisfy:
You can achieve 1. and 2. by using Atomics, but you will have to use something other that double as there is no AtomicDouble. AtomicLong would probably be your best bet.
So you're left with your third requirement - if one succeeds the other must succeed. There is a simple technique that works superbly with atomics and that is using the getAndAdd methods.
class Account {
AtomicLong balance = new AtomicLong ();
}
...
Long oldDebtor = null;
Long oldCreditor = null;
try {
// Increase one.
oldDebtor = debtor.balance.getAndAdd(value);
// Decrease the other.
oldCreditor = creditor.balance.gtAndAdd(-value);
} catch (Exception e) {
// Most likely (but still incredibly unlikely) InterruptedException but theoretically anything.
// Roll back
if ( oldDebtor != null ) {
debtor.getAndAdd(-value);
}
if ( oldCreditor != null ) {
creditor.getAndAdd(value);
}
// Re-throw after cleanup.
throw (e);
}