Threads and Concurrent Programming
Threads may be seen as methods that execute at "the same time" as other methods. Normally, we think sequentially when writing a computer program. From this perspective, only one thing executes at a time. However, with today's multi-core processors, it is possible to literally have several things going on at the very same time while sharing the same memory. There are lots of ways that this is done in the real world, and this chapter goes over them in a way that you can apply to your own projects.
14.6 CASE STUDY: Cooperating Threads
Problem Statement
To illustrate how to address the sorts of problems that can arise when you
try to synchronize threads, let’s consider a simple application in which
several threads use a shared resource. You’re familiar with those take- a-number devices that are used in bakeries to manage a waiting line.
Customers take a number when they arrive, and the clerk announces
who’s next by looking at the device. As customers are called, the clerk
increments the “next customer” counter by one.
There are some obvious potential coordination problems here. The device must keep proper count and can’t skip customers. Nor can it give
the same number to two different customers. Nor can it allow the clerk to
serve nonexistent customers.
Our task is to build a multithreaded simulation that uses a model of a
take-a-number device to coordinate the behavior of customers and a (single) clerk in a bakery waiting line. To help illustrate the various issues
involved in trying to coordinate threads, we will develop more than one
version of the program.
Problem Decomposition
This simulation will use four classes of objects. Figure 14.17 provides a UML representation of the interactions among the objects. The
Figure 14.17: The Bakery creates
the Customer and Clerk threads
and the TakeANumber gadget.
Then Customers request and receive waiting numbers and the
Clerk requests and receives the
number of the next customer to
serve.
TakeANumber object will serve as a model of a take-a-number device.
This is the resource that will be shared by the threads, but it is not a
thread itself. The Customer class, a subclass of Thread, will model the
behavior of a customer who arrives on line and takes a number from the
TakeANumber device. There will be several Customer threads created
that then compete for a space in line. The Clerk thread, which simulates
the behavior of the store clerk, should use the TakeANumber device to
determine who the next customer is and should serve that customer. Finally, there will be a main program that will have the task of creating and starting the various threads. Let’s call this the Bakery class, which gives
us the following list of classes:
- Bakery—creates the threads and starts the simulation.
- TakeANumber—represents the gadget that keeps track of the next customer to be served.
- Clerk—uses the TakeANumber to determine the next customer and will serve the customer.
- Customer—represents the customers who will use the TakeANumber to take their place in line.