to you. That all of these mechanisms (and more) are part of the core language and libraries is
one of the good parts in Java.
But there is a price to pay for using multiple threads in your code. You have to be careful, and
you have to think hard, to make sure that the work being done in one thread doesn't interfere
with the work being done in another. So before we get too carried away with the concurrency
capabilities in Java, we should take a look at the dark side of highly concurrent code.
Running multiple threads is a great way to improve the performance of a program. But be
aware that having multiple threads in a program is like sharing a room with your little brother.
It makes for easy communication, and a lot can happen in the room, but it is really easy for
those who share the room to mess it up because they are sharing too much.
The sharing problem with threads comes because there is no barrier between the data that the
threads can access. Unlike multiple processes, which have no access to memory other than
their own, multiple threads have complete access to anything that the other is doing. This is
an advantage for communication, but it means that you have to be very careful that one thread
does not change the values that another thread is working with, and that each thread sees a
consistent view of the shared world, even when another is updating that world.
We can see this problem when we turn our attention to the StatRecorderImpl class. We have
made this class accessible remotely, allowing programs running elsewhere to obtain rosters
and report box scores to the instances of this class. Server objects like this are generally run
with multiple threads, allowing lots of clients to attach to the server at any time and getting
their requests serviced in parallel. But if we are going to hand out lists of Player objects and
also update those objects when box scores are sent to us, we need to make sure that we aren't
going to report inconsistent statistics about those players. RMI, by default, will spawn a new
thread for every incoming request. So we need to take a look at our StatRecorderImpl to see
where things could go wrong in the multithreaded world.
What we need to worry about is code that updates the state associated with the StatRe-
corderImpl object. Fortunately, there is only one method where this happens: the processS-
core() method, which takes a box score report and updates all of the player statistics for the
players in that game. The implementation of this method is pretty simple:
* Process the box score for a particular team. This