The Cigarette Smokers Problem

Another famous thread synchronization problem in computer science is the cigarette smokers problem. Unfortunately, the thematic vehicle of this example is currently out of favor. Consider a simulation with three smoker threads and one agent thread. Each smoker continuously makes a cigarette and smokes it. But to make a cigarette, a smoker needs three ingredients: tobacco, paper, and matches. One of the smoker threads has only paper, another has only tobacco, and the third has only matches. The agent thread has an infinite supply of all three materials. The three smoker threads are initially blocked. The agent places two randomly chosen (different) ingredients on the table and unblocks the one smoker who has the remaining ingredient. The agent then blocks. The unblocked smoker removes the two ingredients from the table, makes a cigarette, and smokes it for a random amount of time, unblocking the agent on completion of smoking the cigarette. The agent then puts out another random two of the three ingredients, and the cycle repeats.

Write a multi-class multithreaded Java program that uses a monitor to synchronize the agent thread and the three smoker threads. Do not mechanically translate semaphore code into monitor code! The agent thread executes in an agent object created from an agent class. Each smoker thread executes in a smoker object. All smoker objects are created from one smoker class whose constructor is used to specify the ingredient possessed by the smoker object. A driver class with a main method constructs the objects and starts the threads.

Use a single monitor object instantiated from a class Control for synchronization. Each of the four threads invokes a synchronized monitor method for its synchronization. No semaphores are allowed. No synchronized blocks are allowed, only synchronized methods. No busy waiting is allowed. No calls to nap inside a synchronized method are allowed (do not nap while holding the monitor object's lock, that is, while inside a synchronized method or while inside a method called by a synchronized method). Do you see why?

Input Data

The input data to your Java program are (a) the amount of time in seconds that the simulation runs, and (b) the maximum time in seconds that a smoker smokes after rolling a cigarette. The maximum smoke time is used in the random number generator as follows.

int smoking = 1 + (int) random(1000*maxSmoke);
Place these two numbers on the command line for your program to parse. You must parse these numbers from the command line with the GetOpt class (Library Class 2.1). The command line has the form
    % java Smoking -s maxSmoke -R runTime
Remember to give the corresponding variables default values in your program to handle missing command line options.

Animate your program using XtangoAnimator.