在PV操作中会有一个经典的例子就是爸爸妈妈儿子女儿吃水果问题,爸爸妈妈向盘子里放入水果,儿子女儿向盘子取水果。然而爸爸只向盘子放苹果,妈妈只向盘子放橘子,女儿只能吃苹果,儿子只能吃橘子。并且盘子里只能装一个水果,这样爸爸妈妈就要竞争盘子向里面放入水果。而儿子女儿取走水果后必须通知爸爸妈妈向里面放入水果。这就是一个典型的PV操作中互斥与同步混合模型。代码如下:
View Code
class Program
{
private static Semaphore apple = new Semaphore(0, 1);
private static Semaphore pear = new Semaphore(0, 1);
private static Semaphore s=new Semaphore(1,1);
static void Main(string[] args)
{
Thread father = new Thread(new ThreadStart(Father));
Thread mather = new Thread(new ThreadStart(Mather));
Thread son = new Thread(new ThreadStart(Son));
Thread daugther = new Thread(new ThreadStart(Daugther));
father.Name = "爸爸";
mather.Name = "妈妈";
son.Name = "儿子";
daugther.Name = "女儿";
father.Start();
mather.Start();
son.Start();
daugther.Start();
}
private static void Father()
{
Console.WriteLine("{0}准备就绪",Thread.CurrentThread.Name);
s.WaitOne();
Console.WriteLine("{0}放入一个苹果", Thread.CurrentThread.Name);
Thread.Sleep(1000);
apple.Release();
}
private static void Mather()
{
Console.WriteLine("{0}准备就绪", Thread.CurrentThread.Name);
s.WaitOne();
Console.WriteLine("{0}放入一个梨子", Thread.CurrentThread.Name);
Thread.Sleep(1000);
pear.Release();
}
private static void Son()
{
Console.WriteLine("{0}准备就绪", Thread.CurrentThread.Name);
Thread.Sleep(1000);
pear.WaitOne();
Console.WriteLine("{0}取出一个梨子", Thread.CurrentThread.Name);
s.Release();
}
private static void Daugther()
{
Console.WriteLine("{0}准备就绪", Thread.CurrentThread.Name);
Thread.Sleep(1000);
apple.WaitOne();
Console.WriteLine("{0}取出一个苹果", Thread.CurrentThread.Name);
s.Release();
}
}
运行结果如下:
(由Dijkstra首先提出并解决)5个哲学家围绕一张圆桌而坐,桌子上放着5支筷子,每两个哲学家之间放一支;哲学家的动作包括思考和进餐,进餐时需要同时拿起他左边和
右边的两支筷子,思考时则同时将两支筷子放回原处。试想一下,如果哲学家同时思考完问题一人拿一支筷子,每人都等待左边或者右边的人吃完放下筷子,者无人能进餐,只有饿死。那么就必须对此进行PV控制。还有一种情况就是形成死锁,每个哲学家从左边开始取筷子,结果每人一人拿一支筷子互相等待,形成死锁。见下图
View Code
class Program
{
private static Semaphore s1 = new Semaphore(1, 1);
private static Semaphore s2 = new Semaphore(1, 1);
private static Semaphore s3 = new Semaphore(1, 1);
private static Semaphore s4 = new Semaphore(1, 1);
private static Semaphore s5 = new Semaphore(1, 1);
static void Main(string[] args)
{
Thread thread1 = new Thread(new ThreadStart(L1));
Thread thread2 = new Thread(new ThreadStart(L2));
Thread thread3 = new Thread(new ThreadStart(L3));
Thread thread4 = new Thread(new ThreadStart(L4));
Thread thread5 = new Thread(new ThreadStart(L5));
thread1.Start();
thread2.Start();
thread3.Start();
thread4.Start();
thread5.Start();
}
private static void L1()
{
Console.WriteLine("哲学家1思考结束");
s1.WaitOne();
Console.WriteLine("哲学家1可以取左边的筷子");
s2.WaitOne();
Console.WriteLine("哲学家1可以取右边的筷子,并且可以吃饭了");
Console.WriteLine("哲学家1吃饭结束,放下筷子");
Thread.Sleep(1000);
s1.Release();
s2.Release();
}
private static void L2()
{
Console.WriteLine("哲学家2思考结束");
s2.WaitOne();
Console.WriteLine("哲学家2可以取左边的筷子");
s3.WaitOne();
Console.WriteLine("哲学家2可以取右边的筷子,并且可以吃饭了");
Console.WriteLine("哲学家2吃饭结束,放下筷子");
Thread.Sleep(1000);
s2.Release();
s3.Release();
}
private static void L3()
{
Console.WriteLine("哲学家3思考结束");
s3.WaitOne();
Console.WriteLine("哲学家3可以取左边的筷子");
s4.WaitOne();
Console.WriteLine("哲学家3可以取右边的筷子,并且可以吃饭了");
Console.WriteLine("哲学家3吃饭结束,放下筷子");
Thread.Sleep(1000);
s3.Release();
s4.Release();
}
private static void L4()
{
Console.WriteLine("哲学家4思考结束");
s4.WaitOne();
Console.WriteLine("哲学家4可以取左边的筷子");
s5.WaitOne();
Console.WriteLine("哲学家4可以取右边的筷子,并且可以吃饭了");
Console.WriteLine("哲学家4吃饭结束,放下筷子");
Thread.Sleep(1000);
s4.Release();
s5.Release();
}
private static void L5()
{
Console.WriteLine("哲学家5思考结束");
s1.WaitOne();
Console.WriteLine("哲学家5可以取左边的筷子");
s5.WaitOne();
Console.WriteLine("哲学家5可以取右边的筷子,并且可以吃饭了");
Console.WriteLine("哲学家5吃饭结束,放下筷子");
Thread.Sleep(1000);
s1.Release();
s5.Release();
}
}
运行结果如下: