SWEN-342 Engineering of Concurrent & Distributed Software Systems
The Dining Philosophers


Overview

For this activity your team will implement the Dining Philosopher's problem. You'll be able to test it under conditions leading to deadlock as well as those that prevent deadlock.

Note:

You are not allowed to use the synchronized keyword in any code for this activity.

Classes

Fork Class

Create a passive (non-threaded) Fork class; below is the interface to be implemented by Fork.
 
public interface IFork {
    /*
     * A philosopher (attempts to) acquire the fork.
     */
    public void acquire() ;

    /*
     * A philosopher releases the fork.
     */
    public void release() ;
}
There is only a default Fork constructor. Note that a Philosopher acquiring the Fork may have to wait if the Fork is already allocated; when the Fork is released, any waiting Philosopher must be notified. Add state as necessary to the Fork class to support these operations; the initial state is unallocated.

Philosopher Class

The Philosopher class (should be useable in a thread):

public Philosopher(int id, Fork left, Fork right, int nTimes,
                    long thinkMillis, long eatMillis)
Initialize the new Philosopher  thread object. The idleft and right arguments are self-explanatory and nTimes represents the number of think / eat cycles before the Philosopher exits (0 means run forever). The thinkMillis and eatMillis represent the maximum think time and eating time, respectively, for each cycle.
public void run()
Enter a loop executed nTimes (or infinitely if nTimes is 0). On each iteration:

Driver Class

The driver class contains the public static void main( ... ) method; your program will be executed with a command of the form:

java Driver [np] [nt] [tm] [em]

np, nt, tm and em are non-negative integers.

The driver first creates an array of np Forks. Next, np Philosopher threads are created, where Philosopher i's right fork is i and left fork is
(np + i - 1) % np - note that i ranges from 0 to np - 1.

Execution

You should execute your program with different parameters, capture the output, and create one long file Trace.txt from the results. The different traces in Trace.txt should be separated from each other so as to make them easy to distinguish. Add comments to the ends of lines in the trace that illustrate interesting states of the system.

In particular, you should have at least one trace with all right handed philosophers that results in a deadlock. I'd suggest running the program as follows (though other combinations may work better for you):

java Driver 2 0 0 0

You need only show the output from the first fork acquisition leading to the deadlock occurs to the deadlock itself.

Once deadlock has been demonstrated, make sure to commit your code. After successfully committing, modify the code to remove the deadlock. This can be accomplished by breaking any of the four necessary and sufficient requirements for deadlock (see class slides). Run your program again (multiple times) do demonstrate the deadlock no longer occurs. Record at least one of these runs in the Trace.txt file along with a description of what you changed to avoid the deadlock.

Deliverables

Submit your solution by pushing all files to the course repo by the deadline.