Java Reference
In-Depth Information
// Debits require even more checks...
try {
Thread.sleep(150);
} catch(InterruptedException e) {
System.out.println(e);
}
balance -= transaction.getAmount(); // Increment the balance...
transaction.getAccount().setBalance(balance);// Restore account balance
break;
}
default: // We should never get here
System.out.println("Invalid transaction");
System.exit(1);
}
}
}
How It Works
The expression in parentheses following the keyword synchronized specifies the object for which the
synchronization applies. Once one synchronized code block is entered with a given account object, no
other code block or method can be entered that has been synchronized on the same object. For
example, if the block performing credits is executing with a reference to the object accounts[1]
returned by the getAccount() method for the transaction, the execution of the block carrying out
debits cannot be executed for the same object, but it could be executed for a different account.
The object in a synchronized code block acts rather like a baton in a relay race that serves to synchronize the
runners in the team. Only the runner with the baton is allowed to run. The next runner in the team can only
run once they get hold of the baton. Of course, in any race there will be several different batons so you can
have several sets of runners. In the same way, you can specify several different sets of synchronized code
blocks in a class, each controlled by a different object. It is important to realize that code blocks that are
synchronized with respect to a particular object don't have to be in the same class. They can be anywhere in
your program where the appropriate object can be specified.
Note how we had to move the code to access and restore the account balance inside both synchronized
blocks. If we hadn't done this, accessing or restoring the account balance could occur while a
synchronized block was executing. This could obviously cause confusion since a balance could be
restored by a debit transaction after the balance had been retrieved for a credit transaction. This would
cause the effect of the debit to be wiped out.
If you want to verify that we really are overlapping these operations in this example, you can add
output statements to the beginning and end of each method in the class Bank . Outputting the type of
operation, the amount, and whether it is the start or end of the transaction will be sufficient to identify
them. For example, you could modify the doTransaction() method in the Bank class to:
// Perform a transaction
public void doTransaction(Transaction transaction) {
Search WWH ::




Custom Search