...
| 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();
}
}
|
...