CS 552
Fall 1999

Programming Assignment 2: Monitors                                               Due October 12, 1999

This assignment is to be done in teams of two. As part of your documentation, specify team members (name, ID) and a brief description of each member's responsibilities (or how you divided up the work). Also, please specify on the cover page of your hard copy your names and which one of you had submitted the electronic version.

Introduction

You are to write the code to provide the synchronization to control access to a collection of pedestrian bridges. The bridges are used to cross a dangerous, shark-infested river. The picture below illustrates the problem.

Bridges




Specification

You are given a class called Bridges. This class has the following methods that you can call. (More detailed documentation is also available). There are also methods Bridges.toString() and Bridges.verbose(int verbosity) provided to help you with debugging.

Each person is a thread running a Person class, which you must write, that implements the following interface (see also the complete specification.)

Your Person class may also contain any additional methods that you need.

Use a ``monitor'' (a Java class with synchronized methods) as the synchronization mechanism for your solution. Create an instance of the monitor in the main() method and save it as a static field of the ``main'' class so that it can be easily referenced from Person.run().

Your solution must obey the following rules:

  1. Each bridge is strong enough to hold only capacity persons at a time, where capacity is a parameter to the Bridges constructor. Additional people will break the bridge and they all will fall in the river and drown.
  2. Bridges are one-way. If two people try to cross the same bridge in opposite directions at the same time, they will fall into the river.
  3. If there is more than one person wanting to cross the river, as many bridges as possible should be in use at the same time.
  4. People shouldn't wait any longer than necessary to cross the river.
  5. Initially, all the bridges are unoccupied.
If you violate the above rules or call the Bridges methods incorrectly, the people will fall in the river and drown (actually, an exception will be thrown, either Drowning or IllegalArgumentException ).

You may copy these examples of Person.java and Proj2.java and try them out to see how things should work.

You must prepare two solutions to this problem. In the first solution, each person crosses the first available bridge. In the second solution, there is a separate waiting line for each bridge. A newly arriving person gets in the shortest waiting line and waits for a chance to cross that bridge. (The length of the waiting line is the number of people on the same side of the river waiting to cross that particular bridge.) Which solution gives better performance?

Compiling and Running

Create a new directory for this project. You will need to define at least three classes for this project, the ``main'' class, the class Person, and a monitor class. Put the source for each class in a separate .java file (with the same name as the class). Copy the implementation of the Bridges and Drowning classes to your working directory.
    cp /home/fac1/matta/cs552-pa2/*.class .
Then compile and run your program as usual.
    javac Project2.java
    time java Project2
The word ``time'' at the beginning of the second command causes Unix to print a message after the command completes indicating how much CPU time you used. This will give a hint how efficient your solution is (see below).

More details on tests you should run will be posted before the due date.

Hints

You will need a monitor class to coordinate access to the bridges. We'll call it CrossingGuard for this discussion. This class will have to keep track of the state of all the bridges (how many people are currently crossing each bridge and which way they are going). There is no way of getting this information directly from Bridges. (There is a toString method, but that's just for debugging.) CrossingGuard will have a method a person calls when he wants to cross the river.

You should not call Bridges.cross() from a synchronized method of CrossingGuard. If you do so, everything may seem to work fine, but you will get terrible performance. When a thread gets blocked in Bridges.cross(), it will still be holding the monitor lock for CrossingGuard, preventing any other thread from entering any method of CrossingGuard. The result will be that only one person will cross the river at a time, regardless of how many bridges there are and regardless how many people each bridge can hold. Instead, you should have two synchronized methods, one that blocks the caller until it is safe to call Bridges.cross() and the other to be called after Bridges.cross() returns.

For the second solution (where you have a separate waiting line for each bridge), you could still get by with one monitor. Each time a person finished crossing a bridge, he would call notifyAll, waking up all the waiting people. Each one would recheck whether it would be safe for him to cross, and go back to sleep otherwise. Such a solution would not be very efficient. It would be better if you used a separate instance of (another) monitor for each waiting line. Then you would only need to wake up people when there was a good chance they could cross. You would see the difference in the amount of CPU time printed at the end of your job.

See guidelines on What to Submit.


Back to CS 552 home page