CMPSCI 377: Operating Systems
Lab 2: Threads and Synchronization

Due: March 24, 2003 23:30


March 13: A couple of people have asked about adding a start button to their lab 2. Here is a snipet from our implementation that should give you the necessary context. This would go somewhere in your JFrame initialization routine (the same place where you create your JPanel and attach it to the frame).
JToggleButton btStart = new JToggleButton("Run"); 
getContentPane().add(btStart,BorderLayout.NORTH);       // Add button
getContentPane().add(gridcanvas, BorderLayout.CENTER);  // Add panel for drawing

btStart.addActionListener(new ActionListener() {
          public void actionPerformed(ActionEvent ae){
	      if (btStart.getText()=="Run"){

	         btStart.setEnabled(false); //disable the button
March 13: For those of you who are working in groups for lab 2: please hand in one additional file (each person hands in their own copy of this file): lab2.private.txt that estimates your own personal contribution to the project in terms of percentage of work done.

March 2: You may now download and execute our solution: RW.jar (execute using the following: java -jar RW.jar fname

Purpose of Assignment

This assignment will give you experience in the creation and management of multiple, interacting threads.


This lab project will count for 30% of your lab grade (so 11.7% of your final grade). Your grade is broken down as follows:

You may work with one other person in the class. If you choose to do so, please send email to the professor and the TAs in order to indicate who your partner will be and which of the two of you will be handing in the program. Do not share/accept code with/from anyone else or from the net.

Where to do your work

For this lab, place your final submission in the following directory:


If your files are not located in the right place or our robot cannot read your homework at the time of submission, then we will not be able to grade it. In order to make sure that our robot can pick up your program, please check things by executing the ~fagg/bin/checkhw script with the lab2 parameter.

You need only hand-in one copy of your program.

The Problem

For this lab, we are solving a problem involving multiple, coordinated robots. As you have already discovered in lab 1, an input file specifies a map, some set of robots of various colors (red, green, and blue), and some set of goals (red, green, blue, and black). The robots and goals "live" on a discrete grid of a specific size (think graph paper). Some grid squares are occupied by obstacles. The task is for the individual robots to move around on the grid and "eat" goals without running into each other or any obstacles.

Your program must:

  1. As in lab 1, your program must parse the map file and place the information into an appropriate data structure (one is provided). Your program should detect and trap any errors that might exist in the file and display an appropriate error message. The file format is identical to that of lab 1.

  2. Create a thread that will control the movements of each robot (if there are N robots, then there will be N threads). This thread must run at NORM_PRIORITY. Be careful that the individual robot threads do not make conflicting updates to the common data structures.

  3. Create a thread that will update the display at regular intervals. This thread must run at NORM_PRIORITY+1 and execute at approximately 30 millisecond intervals.

  4. Create a thread that will write the position of each robot to a file ("log.txt") at regular (50 ms) intervals. This thread must also run at NORM_PRIORITY+1. Be careful to ensure that only valid data is written to the file. See the example map1.log for the map1.txt file. See below for more details of the format of the log file.

  5. Create one thread for each color class of robot (so a total of 3). This thread will compute the distance matrices used in making robot movement decisions.

  6. In order to ensure that the different threads do not interfere with one-another, you must identify their critical sections and use the appropriate synchronization primitives in your code (see below for a few more hints on this).

The rules for the world physics are as follows:

  1. Robots may only eat goals that are either black or their own color.

  2. Once a goal is eaten, it is removed from the display and cannot be eaten again. This is indicated in the data structure by setting isEaten to true (see below).

  3. At each step, a robot may only move one square in the up/down/left/right directions.

  4. Robots may not move to a grid square that is occupied by an obstacle, by another robot, or by goals that are not black or their own color (i.e., goals of other colors are considered obstacles).

  5. When a robot no longer has edible goals to consume, it dies and stops moving. This is indicated in the data structure by setting bDead to true (see below). Once a robot is dead, it can no longer move.

What we provide:

  1. A predefined, public data structure that describes the grid and and the locations of the robots, obstacles and goals. This is defined in

  2. A predefined, public data structure that describes a goal. This is defined in

  3. A predefined data structure that extends the thread class and defines the Abstract_Robot class ( This class must be extended by you to implement the movement of the robots and to handle all of the necessary bookkeeping.

  4. A predefined class Abstract_Distance ( that provides the functionality for calculating the distance matrix for each robot color class. In particular, this abstract class provides:
    1. A distance matrix (dist[][]) that represents the distance from any grid square to the closest, appropriate goal (black or one that matches the color of the robot). A value of MAX_VALUE indicates that an obstacle or a dead robot is located at this grid square. A value of -1 indicates that there is no goal that can be reached from this grid location.

    2. A predefined method (SetDist()) that takes information about the obstacles, goals, and robots and fills in the distance data structure with the appropriate values.

    You must extend this class by providing a run() method that selects the appropriate time at which to recalculate the distance matrix. It is important that you trigger this recalculation in as efficient manner as possible (i.e., no busy waiting). Hint: think about the tools that we have been learning about in class.

    Robots of the same color will share a single instance of distance matrix. Each time that a robot is going to take a next step, it should check the distance matrix and choose to move to the nearby grid cell that is of minimum value that is also free of obstacles, robots, and non-matching goals. If all values are -1, it means that no goals are currently reachable by the robot; in this case, the robot should not move.

  5. An implementation of a semaphore object. This is defined in This is the only synchronization primitive that you should use (unless you talk to the Instructor first).

Other Notes:
  1. Your program must start by creating and painting the window. Only after a user input (e.g., by pressing of a 'Start' button or a key) should the robots start moving.

  2. Robots must sleep for 200 milliseconds between steps so as to give other robots an opportunity to move.

  3. Once the robots have completed their movements, the window must continue to stay visible until explicitly killed by the user.

  4. The distance matrices must be explicitly updated under two conditions: when a robot eats a goal and when a robot dies.

What to Hand In

Place in your Hand-In directory the following:

We will test your program with a variety of maps, including:

Checking Your Results

We will use the log file to partially check the correctness of your program. So - it is essential that your log file be in the appropriate format. This format is as follows:

<file> := <line>+
<line> := <N> goals left; <robot>+
<N> := [0...9]+
<robot> := <DEAD>? Robot<N> <color> At [<N>,<N>];
<DEAD> := (Dead)
<color> := Red | Green | Blue

In particular:

We have provided the checklog script that will scan your log.txt file and confirm that no two robots ever occupy the same grid square, and that all goals are consumed by the end of the run (this script should be in your executable path). The script terminates with an "ALL OK" if these two conditions are met. The log files generated by your program should generally check out OK; if they do not, this may be indicative of a problem in your program. Please be sure to ask if there are any questions.

We will also use this script to check your programs (but note that this will not be the only check that we do).

Here are the log files that our program generates (note that these are not unique):

Here are some log files that our program generates when proper thread synchronization is not used:

Some Comments/Hints

Java Hints

This page is online at
Andrew H. Fagg