gcc -o foo foo.c -L/home/linux/ieng6/cs120f/hw -lthread
Implement the semaphore-based readers/writers algorithm given in Lecture 6 in C using the threads package. You should implement three reader threads and three writer threads. You will find it easier to have t_start start a thread that creates the two conditions - one for the semaphore mutex and one for the semaphore r_or_w - and t_forks the three reader and three writer threads. The parameter to the thread should be a unique name for the thread (for example, you could name the reader threads R1, R2 and R3).
printf("%s starts reading\n", name);
t_yield();
printf("%s stops reading\n", name);
where name is unique name you gave to this reader thread. Similarly, each writer should execute a look so that it tries to enter the Write section three times. The Write section should be:
printf("%s starts writing\n", name);
t_yield();
printf("%s stops writing\n", name);
where name is unique name you gave to this writer thread.
Run your program to verify that it is behaving the way it should. This is the program whose listing we'd like you to turn in along with the output it generates.
The monitor will be the class Table that has two methods: one called StartEating(i) which means that Philosopher i wishes to eat, and one called StopEating(i) which means that Philosopher i stops eating. The file Table.java is the file you'll need to modify to implement this monitor. In StartEating(i), Philosopher i checks to see if either of her neighbors is eating; if so, then i is hungry and waits. StopEating(i) turns the Philosopher's state back to thinking, which may allow a hungry neighbor to start eating. The class also includes a place for you to implement toString: the Philosopher class uses this to print the current states of the philosophers in a convenient manner. This string should contain five character - the first represents the state of Philosopher 0, the second the state of Philosopher 1, and so on. Use the character 'T' to indicate thinking, 'H' for hungry, and 'E' for eating. For example, "THETE" means Philosopher 0 and 3 are thinking, Philosopher 1 is hungry, and Philosophers 2 and 4 are eating. Note that this class has a constructor, in which we've already supplied some code. You'll need to do more.
The file Philosopher.java is the class that implements a philosopher thread, and DiningPhilosophers.java is the class that implements the program: this is the class that has main. You won't have to change either of these files.
To give you a template for a Java monitor, we've also posted BSem.java, which is a java class that implements a binary semaphore (that is, a mutex semaphore). Don't use this class in your implementation of Table; instead, look at it to show you the syntax Java uses for writing monitors.
Turn in a listing of Table.java and the output you generate from running DiningPhilosophers.
In your implementation, you have three options for the case where signal(s) is done on a semaphore that has already attained its maximum value. You can (i) treat the operation as a no-op; (ii) block the operation until some other thread executes wait(s); (iii) raise an exception (that, if not caught, causes the process to terminate).
For each of these, give a positive attribute and a negative attribute for using that solution. Which do you think is the best, and why?
One decision to make with an await construct is defining exactly when the boolean expression is evaluated. Of course, when await(B) is initially executed, if B is true then the thread need not wait. The interesting case is when should B be re-evaluated for threads that are waiting for B to become true.