Java Reference
In-Depth Information
/**
* Update the batting statistics for a player for a particular game.
* This method assumes that the player is associated with some batting
* statistics (e.g., that there is a {@link Batter} object associated
* with the player.)
* @param batter Player whose batting statistics are to be updated
* @param results a list of the batting results for a particular game
*/
private void updateBatting(Player batter, List<Batter.AtBatResult> results) {
Batter batStats = batter.asBatter();
synchronized (batter) {
for (Batter.AtBatResult r : results) {
batStats.atBat(r);
}
}
}
Changing the method in this way will ensure that no other thread can access the particular bat-
ter object while the updateBatting() method is running. Updates will be done one at a time,
and rosters will need to wait until the update is done to gain access to the Batter (which is
part of the Player ). Doing the same sort of locking for the other updates should ensure that
those calling getRoster() will at least see consistent statistics on particular players. It will
still be possible to get a roster that has some players updated for a game that hasn't been re-
corded against other players, but that is something we can live with.
Adding locks to our code can ensure that only a single thread accesses the object that is locked,
helping us to avoid some concurrency bugs. But as things get more complex, locking also
introduces a new class of bugs that revolve around the locks themselves. Suppose, for ex-
ample, that we have implemented a way to update the fielding results for a game. Further,
instead of just passing the batting results for a particular player into updateBatting() , we
hand in a structure that contains both the batting and the fielding results. Likewise, for an
updateFielding() method, we hand in the same structure. Because we are paranoid, at the
end of updateBatting() , we call updateFielding() (assuming we have a way of checking
whether it has already been called), and when we end the updateFielding() method, we call
updateBatting() (also assuming that we can find out whether it has already been called).
This will work fine, up until the time that the statistics for the same player are simultaneously
being updated by two threads, one of which is starting with the updateBatting() method
and the other starting at the updateFielding() method. The thread starting with updateBat-
ting() will get a lock on the BattingImpl object for the player at the same time the up-
Search WWH ::




Custom Search