MC78 Lab 1: Races and Monitors (Fall 1996)

Due: September 24, 1996

Goals of the lab

In this lab you (and a partner) will read and understand a client/server pair of programs written in Java, each of which involves concurrency. Each program has a race condition, which you must find, that could lead the program not to behave correctly if the timing of the threads worked out just wrong. You will write a description of specifically what could go wrong and under what circumstance. Then you will empirically verify your predictions by introducing time delays into the programs at the appropriate points so as to transform the races from being a problem only under unlucky circumstances into being easily triggered, and you will document the buggy behavior exhibited. Finally, you will fix the problems using Java's monitors feature, by adding the necessary "synchronized" keyword to the appropriate methods and verifying that this indeed made the buggy behavior go away.

The programs

This lab involves three Java programs: Flip, NetFlip, and FlipServer. The Flip program is a single-player non-networked puzzle program that doesn't involve any concurrency issues. It isn't really part of the lab proper, but is the basis for the NetFlip program, which is simply a multi-user networked version of Flip in which all the users are playing together on a single puzzle: they can all see the same board and can all manipulate it. The way this is accomplished is that the various NetFlip games on the net are all tied together by communication with a single FlipServer. The hostname of the computer that the FlipServer is running on needs to be given as a command line parameter to the NetFlip program.

Java source files

The Flip program is contained entirely in the source file, which defines a single class, Flip, in the EDU.gac.max.flip package.

The NetFlip program re-uses that same source file and adds a source file, which defines two classes, NetFlip and NetInterface, both of which are again in the EDU.gac.max.flip package. (The package these classes are in implies that the files should be in a directory EDU/gac/max/flip.)

The FlipServer program is contained in the source file, which defines two classes, FlipServer and ClientConnectionThread, both in the EDU.gac.max.flipserver package. In addition, the FlipServer program makes use of a library class (in addition to the standard Java libraries), MulticastOutputStream, from the package. The source for that class is in, but you can safely treat this class as a black box. In particular, it is thread-safe (all its methods are synchronized), so its internal details play no role in the race conditions.

How to compile and run Java programs

To use Java, you'll need to add /usr/local/java/bin to your search path. You can do this using the command set path=(/usr/local/java/bin $path). Once you have done that, you can compile a java program by, for example, saying javac EDU/gac/max/flip/ Note that the file needs to be down four levels deep in subdirectories to correspond to the Java package EDU.gac.max.flip that it is in. To run the program, you can then say java EDU.gac.max.flip.Flip. Note that the command line argument to the java interpreter is the name of the class, not the filename. For a program such as NetFlip that expects an additional command line argument of its own (the hostname of the FlipServer), you would use a command like java EDU.gac.max.flifp.NetFlip localhost. (The hostname localhost is a special name that always refers to the machine you are on, regardless of which machine you are on. This will be handy for most of the lab, though at points you may want try sharing a FlipServer with one or more teams on other machines.) You can run any of these programs in the background by putting a & at the end of the command line, so that your shell is available for issuing other commands from. That way you can start a FlipServer and as many NetFlips as you want all from one shell.

How to insert a time delay

To insert a time delay, say of five seconds, into a program at some point, just insert the following Java statement: try{Thread.sleep(5000);}catch(Exception e){}. This sleeps for 5000 milliseconds (i.e., 5 seconds), and if an exception occurs (such as would be caused if the sleep were explicitly interrupted), ignores it.

What to turn in

Turn in a jointly-authored lab report containing the following information:

Instructor: Max Hailperin