...
Code Block | ||
---|---|---|
| ||
final class BankAccount {
private double balanceAmount; // Total amount in bank account
private BankAccount(double balance) {
this.balanceAmount = balance;
}
// Deposits the amount from this object instance to BankAccount instance argument ba
private void depositAmount(BankAccount ba, double amount) {
synchronized (this) {
synchronized(ba) {
if(amount > balanceAmount) {
throw new IllegalArgumentException("Transfer cannot be completed");
}
ba.balanceAmount += amount;
this.balanceAmount -= amount;
}
}
}
public static void initiateTransfer(final BankAccount first,
final BankAccount second, final double amount) {
Thread t = new Thread(new Runnable() {
public void run() {
first.depositAmount(second, amount);
}
});
t.start();
}
}
|
...
Code Block | ||
---|---|---|
| ||
final class BankAccount { private double balanceAmount; // Total amount in bank account private static final Object lock = new Object(); private BankAccount(double balance) { this.balanceAmount = balance; } // Deposits the amount from this object instance to BankAccount instance argument ba private void depositAmount(BankAccount ba, double amount) { synchronized (lock) { if (amount > balanceAmount) { throw new IllegalArgumentException("Transfer cannot be completed"); } ba.balanceAmount += amount; this.balanceAmount -= amount; } } public static void initiateTransfer(final BankAccount first, final BankAccount second, final double amount) { Thread t = new Thread(new Runnable() { public void run() { first.depositAmount(second, amount); } }); t.start(); } } |
...
Code Block | ||
---|---|---|
| ||
final class BankAccount implements Comparable<BankAccount> { private double balanceAmount; // Total amount in bank account private final Object lock; private final long id; // Unique for each BankAccount private static long nextID = 0; // Next unused id private BankAccount(double balance) { this.balanceAmount = balance; this.lock = new Object(); this.id = this.nextID++; } public int compareTo(BankAccount ba) { // No need to check for overflow because the type long is large // enough to hold the required number of bank accounts return (this.id - ba.id); } // Deposits the amount from this object instance to BankAccount instance argument ba public void depositAmount(BankAccount ba, double amount) { BankAccount former, latter; if (compareTo(ba) < 0) { former = this; latter = ba; } else { former = ba; latter = this; } synchronized (former) { synchronized (latter) { if (amount > balanceAmount) { throw new IllegalArgumentException("Transfer cannot be completed"); } ba.balanceAmount += amount; this.balanceAmount -= amount; } } } public static void initiateTransfer(final BankAccount first, final BankAccount second, final double amount) { Thread t = new Thread(new Runnable() { public void run() { first.depositAmount(second, amount); } }); t.start(); } } |
...
Code Block | ||
---|---|---|
| ||
final class BankAccount { private double balanceAmount; // Total amount in bank account private final Lock lock = new ReentrantLock(); private final Random number = new Random(123L); private BankAccount(double balance) { this.balanceAmount = balance; } // Deposits the amount from this object instance to BankAccount instance argument ba private void depositAmount(BankAccount ba, double amount) throws InterruptedException { while (true) { if (this.lock.tryLock()) { try { if (ba.lock.tryLock()) { try { if (amount > balanceAmount) { throw new IllegalArgumentException("Transfer cannot be completed"); } ba.balanceAmount += amount; this.balanceAmount -= amount; break; } finally { ba.lock.unlock(); } } } finally { this.lock.unlock(); } } int n = number.nextInt(1000); int TIME = 1000 + n; // 1 second + random delay to prevent livelock Thread.sleep(TIME); } } public static void initiateTransfer(final BankAccount first, final BankAccount second, final double amount) { Thread t = new Thread(new Runnable() { public void run() { try { first.depositAmount(second, amount); } catch (InterruptedException e) { Thread.currentThread().interrupt(); // Reset interrupted status } } }); t.start(); } } |
...