The document compares approaches to handling bank account transactions in Java and Clojure. In Java, account balances must be synchronized to prevent race conditions during transfers. Clojure uses software transactional memory via refs and dosync to coordinate concurrent updates to account balances in a transactional manner without explicit locking. This provides a more functional approach compared to the object-oriented Java implementation.
2. public class Account {
private long balance;
private final int accountNo;
public void debit(long debitAmount) {
this.balance -= debitAmount;
}
public void credit(long creditAmount) {
this.balance += creditAmount;
}
public long getBalance() {
return this.balance;
}
public void getAccountNo() {
return this.accountNo;
}
}
3. public class Account {
private volatile long balance;
private final int accountNo;
public synchronized void debit(long debitAmount) {
this.balance -= debitAmount;
}
public synchronized void credit(long creditAmount) {
this.balance += creditAmount;
}
public synchronized long getBalance() {
return this.balance;
}
public void getAccountNo() {
return this.accountNo;
}
}
4. public void transfer(Account fromAccount, Account toAccount,
long amount) throws Exception {
if (fromAccount.getBalance() < amount) {
throw new Exception("Not enough money!");
}
fromAccount.debit(amount);
toAccount.credit(amount);
}
5. public void transfer(Account fromAccount, Account toAccount,
long amount) throws Exception {
synchronized (fromAccount) {
synchronized (toAccount) {
if (fromAccount.getBalance() < amount) {
throw new Exception("Not enough money!");
}
fromAccount.debit(amount);
toAccount.credit(amount);
}
}
}