Return to the Banking Example

So, we just survived the ATM withdrawal problem. It turns out that this problem occurred so infrequently that the total cash involved with the problem transactions was only a few thousand dollars. Luckily, the bank kept records that were good enough to recover the cash. While our manager did not like the fact that we caused a major panic among the upper-level managers, she was somewhat impressed that we were able to track down the problem. While she still does not trust us completely, we still have a job and are able to design and enhance different parts of the ATM system.

The first thing we do is to look at our existing ATM code: we check and double check every piece of code for race conditions, using the synchronized mechanisms that we’ve learned so far to resolve the problems. Everything seems to be going well until one day the president of the bank receives a phone call from an irate customer. This customer did a balance inquiry at the ATM that showed a balance of $300. Immediately, he attempted to withdraw $290, but could not.

It turns out that in the very short period of time between when the customer checked his balance and attempted to withdraw the money, his wife withdrew $100 from another ATM. Even though the “correct” thing happened, it turned into a big political problem for the bank when the husband threatened to remove his $1 million business account from the bank if the bank “couldn’t keep their records straight.” So the bank established a new policy that only one ATM could operate on an account at the same time.

This means that we need a new lock scope for the account: the ATM class must be able to lock the account for the duration of a session with a user. This session could comprise transactions that span multiple methods in the ATM class, so the synchronized blocks and synchronized methods that we’ve learned about so far aren’t sufficient to solve this problem: we need a lock that spans multiple methods.

Fortunately, we’ve already developed the BusyFlag class, so we’re in position to solve this problem with little effort:

public class AutomatedTellerMachine extends Teller {
    Account a;

    public boolean synchronized login(String name, String password) {
        if (a != null)
            throw new IllegalArgumentException("Already logged in");
        a = verifyAccount(name, password);
        if (a == null)
            return false;
        a.lock();
        return true;
    }
 
    public void withdraw(float amount) {
        if (a.deduct(amount))
            dispense(amount);
        printReceipt();
    }
 
    public void balanceInquiry() {
        printBalance(a.balance());
    }
 
    public void synchronized logoff() {
        a.unlock();
        a = null;
    }
}
 
class Account {
    private float total;
    private BusyFlag flag = new BusyFlag();
 
    public synchronized boolean deduct(float t) {
        if (t <= total) {
            total -= t;
            return true;
        }
        else return false;
    }
 
    public synchronized float balance() {
        return total;
    }
 
    public void lock() {
        flag.getBusyFlag();
    }
 
    public void unlock() {
        flag.freeBusyFlag();
    }
}

By using a BusyFlag lock, we’re now able to lock at a “session” scope by grabbing the busyflag when the user logs into the ATM and releasing the busyflag when the user logs off the ATM. Locking at this scope cannot be directly achieved with the synchronization primitives within Java.

Being proud of the BusyFlag class, we now place the code into a class library, where it is accepted by the whole development team for the ATM project. Although it is a very simple class, it is also one of the most functional and is used in practically every part of the ATM system. However, we’ll point out now that our current implementation of the BusyFlag class, while correct, is still suboptimal, but we can’t solve that problem until we learn about the tools in the next chapter.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset