Dining Philosophers Using Locks and Condition Variables: Design Document
Ethan Miller
Fall 2007
Purpose
The purpose of this project is to design the dining philosopher monitor using Lock and Condition only.
Available Resources
We can use both the Lock and Condition classes to solve the dining philosophers problem. The dining philosopher class has the following public interfaces that we must support:
class PhilMonitor { Public: PhilMonitor(); ~PhilMonitor (); void PickUp(int i); // must be called before eating to make sure that i // can take the forks to my left and right hand side void PutDown(int i); // must be called after eating to put down the // forks i used to eat with void Test(int i); // make sure phil 'i' can eat. Private: // I need some more in here };
All I have to do in my design is describe the private members
of the class and how they are used in the three main functions:
PickUp()
, PutDown()
,
and Test(). Note that I will not be saying anything
about Lock and Condition as they were given
to me.
Design
The overall design is to have a single thread for each philosopher.
Each philosopher calls PickUp()
before
starting to eat and PutDown()
after getting full.
There's a single function—Test()—that is used to determine whether a
particular philosopher can eat at the current time. This function determines
whether a particular philosopher can eat; if so, the philosopher is awakened.
Test() never puts a philosopher to sleep, and the wakeup is done by condition
variables so it's OK to call Test() from the thread of the philosopher
being "tested" (any signal on the condition variable will be discarded).
Private members and public functions are explained below.
New private members
int State[5] // Each phil. has his own state. 0 = thinking, 1 = hungry, // 2 = eating. Condition self[5] // Each phil. has his own condition variable. Lock L // Lock to enter and leave the monitor.
Design of each function
void PickUp(int i) Acquire the lock L Set my state to Hungry Test to see if I can get the forks to my right and left [see Test()] If I am not Eating, then I have to wait on my condition variable 'self' Release the lock L void PutDown(int i) Acquire the lock L Set my state to Thinking Test to see if my left neighbor is Hungry [see Test()] Test to see if my right neighbor is Hungry [see Test()] Release the lock L void Test(int i) No lock is needed since Test is called within PickUp and PutDown. If phil. 'i' is hungry and neither of his neighbors is eating then Set phil. i's state to Eating Wake up phil. i from his condition variable sleep
We also need to implement the code for each philosopher thread as follows:
Phil (int i) forever: PickUp (i) // Wait for some time while eating... PutDown (i) // Wait for some time while thinking...
Testing
The test strategy for this design will be to try this out with varying interrupt behavior. Basically, we can run this many times and make sure that it works. Another test we may want to run is to vary the think time and eating time for different philosophers, making sure that reducing thinking time still keeps things fair (and working).
Last updated 28 Sep 2009 by Maria Hybinette and 29 Sep 2008 by Darrell Long and perhaps by Jeff LeFevre