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);
}
}
|