A9: | There are many solutions. Here is one based on not grabbing a chopstick until both are available: using System; using System.Threading; class Stick { //Sticks available are designated as true bool[] chopStick = {true, true, true, true, true}; // Attempt to pick up left and right chopstick public void GetSticks(int left, int right) { lock (this) { // Release lock and wait until both chopsticks are free while (!chopStick[left] && !chopStick[right]) Monitor.Wait(this); chopStick[right] = false; chopStick[left] = false; } } // Put chopsticks down public void FreeSticks(int left, int right) { lock(this) { chopStick[right] = true; chopStick[left] = true; // Signal threads in queue that chopsticks are available Monitor.PulseAll(this); } } } class Philosopher { int n; // Philosopher number int eatDelay; int thinkDelay; int left, right; Stick chopSticks; public Philosopher (int n, int thinkTime,int eatTime, Stick sticks) { this.n = n; this.eatDelay = eatTime; this.thinkDelay = thinkTime; this.chopSticks = sticks; // Fifth philosopher has chopstick 1 on left left = n == 5 ? 1 : n+1; right = n; new Thread(new ThreadStart(Run)).Start(); } public void Run() { while(true) { try { // Philosopher thinks for random amount of time Thread.Sleep(thinkDelay); chopSticks.GetSticks(left-1, right-1); Console.WriteLine("Philosopher {0} is eating for [1} ms ",n, eatDelay); Thread.Sleep(eatDelay); chopSticks.FreeSticks(left-1, right-1); } catch { return; } } } } // End of class Philosopher public class Diners { public static void Main() { Stick sticks = new Stick(); // Create thread for each philosopher // Eat time is random Random r = new Random(DateTime.Now.Millisecond); new Philosopher(1, 100, r.Next(500), sticks); new Philosopher(2, 200, r.Next(500), sticks); new Philosopher(3, 300, r.Next(500), sticks); new Philosopher(4, 400, r.Next(500), sticks); new Philosopher(5, 500, r.Next(500), sticks); } }
|