Assignment #6: Threads and Critical Sections and Low-Level Synchronization

This is a tricky assignment that illustrates threads, synchronization, and critical sections. You will write a simulation of the Ticketmaster Phone system. Here we will assume that there are five lines, but only three operators. When a phone call arrives, we see if there is a free line. If so, the phone rings; otherwise it is busy. Once the phone rings, we wait until there is a free operator, and when we get one, we pretend to get service. Each phone call is represented by a thread, and you will have more threads running than phone lines. There are several components to the project.

Semaphor and Mutex

First you will complete the Semaphor and write the Mutex class. Semaphor.java is your starting point. A Semaphor is use to control entry to a critical section with a limit of how many threads are allowed to be simultaneously active. To enter the critical section you must gain ownership with obtain, and upon leaving the critical section you should release so a waiting thread can enter. The Semaphor maintains the limit of threads concurrently allowed in its critical section, and a list of the threads currently (in an ArrayList). The skeleton is already written, you need to follow the embedded comments to complete the code. A Mutex is a semaphor with a limit of one thread in the critical section. Use inheritance for a quick implementation. Note: there is a Semaphore class in the Java 1.5 library, but please write your own, for the practice. Do it both ways: use the synchronization primitives and then rewrite using Lock and Condition objects.

The PhoneCall Class and main

A phone call is represented by a PhoneCall class that contains a caller's id as private data member, set in its constructor. PhoneCall will extend Thread and provide a run method. It will also contain a host of static data members, including semaphors and mutexes that are shared and control the synchronization. To start with, implement a constructor, and provide a run that simply prints a message, so you know that the thread is running, sleeps for a few seconds (use Thread.sleep), and then prints a message before the thread ends. Later you will do the meaty part of the simulation.

Your main routine will declare an array of threads that will represent each phone call. Then, write a loop that constructs PhoneCall objects to initialize the array. Then, write a loop that starts each PhoneCall thread. When main terminates print a message that the simulation is over. If you run the program, you'll notice that the message comes early. You will want main to block until all the other threads complete and to do that, you should have another loop that uses join on each thread.

The Synchronization

Once you have the threads going, you'll want to do the real part of the simulation. Your PhoneCall class should declare the following static data:
    private static int NUM_OPERATORS = 3;
    private static int NUM_LINES = 5;
    private static int connected = 0;    // Callers that are connected
    private static Mutex connectedMutex = new Mutex( );
    private static Semaphor operators = new Semaphor( NUM_OPERATORS );
The variable connected tells how many callers are currently connected (a call attempt is declared busy if connected==NUM_LINES). Access to connected must be controlled by a critical section, and is done by using the connectedMutex. The operators semaphor is used once a call connects. Here is a sketch of the run method for PhoneCall:
  1. Print that an attempt to connect has been made
  2. Check if the connection can be made
  3. Wait for an operator to be available (use a semaphor)
  4. Print a message that the order is being taken
  5. Simulate an order by sleeping for a few seconds
  6. Print a message that the order is complete (and update the semaphor)
  7. Update connected (do you need a critical section?)
  8. Print a message that the call is over

Test Program

Test your program by running with 10 phone calls. In main, delay the last two phone calls enough so that the line will not be busy.