UNIVERSITY OF WISCONSIN-MADISON
Computer Sciences Department | ||
CS 537
Spring 2000 | A. Arpaci-Dusseau | |
Sample Problems #2 |
Below is code that attempts to solve this problem. The philosopher constructor is called five times in the main method (each time with a parameter 0 to 4 indicating the id of the philosopher) and then 5 philosopher threads are created and started. Think() and Eat() are methods provided to you (already written). You don't know how long each of these takes to complete.
Unfortunately, this code makes a timing assumption about how it is used, can have deadlock even when used "correctly", and does not initialize the value of the semaphores.
For this problem you need to do three things:
The following code might not work correctly if the scheduler decides to start up and schedule a philosopher thread before the semaphore associated with another philosopher has been created and initialized.
for (i = 0; i < philCount; i++) { p[i] = new Philosopher(i); t[i] = new Thread(p[i]); t[i].start(); }
Code that works correctly no matter how scheduler decides to run the philosopher threads:
for (i = 0; i < philCount; i++) { p[i] = new Philosopher(i); t[i] = new Thread(p[i]); } for (i = 0; i < philCount; i++) { t[i].start(); }
class Philosopher implements Runnable{ private static Semaphore chopstick[5]; private int p; Philosopher (int id) { p = id; chopstick[id] = new Semaphore(1); } public void run() { while (1) { Think(); if (p!=0) { fork[p].P(); fork[(p + 1) % 5].P(); } else { chopstick[(p + 1) % 5].P(); chopstick[p].P(); } Eat(); chopstick[p].V(); chopstick[(p + 1) % 5].V(); } } } |
Below is the skeleton of a solution and you should fill in the details. Make whatever additions or changes you feel necessary.
class Semaphore { private int count; public Semaphore (int i) { count = i; public synchronized void P() { while (count == 0) { try { wait(); } catch (InterruptedException e) { } } count--; public synchronized void V() { count++; notify(); } } |
Busses and both types of passengers arrive at random. As buses arrive, your are to fill them up with passengers. Once a bus is full (containing 6 non-wheelchair, and 4 wheelchair passengers), it is allowed to leave the terminal, along with its passengers.
You are responsible only for loading the passengers on the bus and having the bus depart. You don't need to worry about what happens to the busses or passengers after they leave. Each bus thread has available to it the methods ArriveAtTerminal(), OpenDoors(), CloseDoors(), and DepartTerminal(). You don't know how long each of these takes to complete.
Each passenger thread has available to it the methods ArriveAtTerminal() and GetOnBus(). After a passenger thread is safely on the bus, or a bus thread has left the terminal, that thread may terminate (exit).
Your assignment is to write the code that coordinates the buses and the passengers. Write your solution using semaphores as the synchronization mechanism. The syntax will be Java (but don't use synchronized methods!), extended with the Semaphore class as shown in the previous problem. Assume that each bus is a thread, and that the passenger is a thread. You are to define the semaphores that are to be used and how they are initialized. You shouldn't need to define any other shared state variables. You are to then write the code that the two different types of passengers will use, and the code for the buses. Create whatever other methods that you require.
Assume that threads are randomly created (by some code that we provide) and call either the Bus(), WheelPassenger(), or NonWheelPassenger() method. The BusStation() constructor will be called only once, at the start of the program.
class BusStation { // Declare Semaphores here static Semaphore let_wheel_in; static Semaphore let_nonwheel_in; static Semaphore handshake; static Semaphore bus_lock; |
public BusStation() { // Initialize semaphores here let_wheel_in = new Semaphore(0); let_nonwheel_in = new Semaphore(0); handshake = new Semaphore(0); bus_lock = new Semaphore(1); } |
public static void Bus() { ArriveAtTerminal(); // Call OpenDoors(), CloseDoors() with other code as appropriate bus_lock.P(); OpenDoors(); for (int i = 0; i<4; i++) { let_wheel_in.V(); handshake.P(); } for (i = 0; i< 6; i++) { let_nonwheel_in.V(); handshake.P(); } bus_lock.V(); CloseDoors(); DepartTerminal(); } |
void public static WheelPassenger() { ArriveAtTerminal(); // Call GetOnBus as appropriate let_wheel_in.P(); GetOnBus(); handshake.V(); } |
void public static NonWheelPassenger() { ArriveAtTerminal(); // Call GetOnBus() as appropriate let_nonwheel_in.P(); handshake.V(); } } |