[摘要]撰文:周翔这是我在上操作系统课的那个学期写的一段程序,并组织成了一篇文章。当初被我的挚友曾毅发表在CSTC的论坛上:http://cstc.net.cn/bbs/viewtopic.php?t=45...
撰文:周翔
这是我在上操作系统课的那个学期写的一段程序,并组织成了一篇文章。当初被我的挚友曾毅发表在CSTC的论坛上:http://cstc.net.cn/bbs/viewtopic.php?t=457,在此,我把它贴在这儿,希望对大家有所裨益。 
学操作系统的进程同步都要涉及到三个经典问题:生产者-消费者问题、读者-写者问题和哲学家就餐问题。下面来介绍一下哲学家就餐问题: 
哲学家就餐问题中,一组哲学家围坐在一个圆桌旁,每个哲学家的左边都只有一只筷子(当然他的右边也有一只筷子,但是这是他右边哲学家的左边的筷子),他们吃完了就思考,思考了一会就会饿,饿了就想吃,然而,为了吃饭,他们必须获得左边和右边的筷子。当每个哲学家只拿有一只筷子的时候,会坐者等另一只筷子,在每个哲学家都只拿一个筷子的时候,就会发生死锁。传统的解决死锁问题的方法是引用管程的概念,但是在C#中来实现的话可以使System.Threading中的mutex为每个哲学家来声名两个信号量RightChopStick和LeftChopStick,在主程序中用5个mutex赋值给它,用WaitHandle来实现对筷子的独占访问。这个例子是用windows图形界面实现,用事件来通知界面哲学家的状态。 
以下是代码(在vs.net 下运行通过): 
//DiningPhilosophers.cs----------code:seafrog----------------------------------------------------- 
using System; 
using System.Threading; 
using System.Windows.Forms; 
using seafrog.Threading; 
using seafrog.Philosopher; 
namespace DiningPhilosophers 
{ 
public class Form1 : System.Windows.Forms.Form 
{ 
private System.Windows.Forms.Button button1; 
private System.ComponentModel.Container components = null; 
private System.Windows.Forms.ListBox listBox1; 
private Philosopher[] p=new Philosopher[5]; 
public Form1() 
{ 
InitializeComponent(); 
Mutex[] chopSticks=new Mutex[5]; 
for(int i=0;i<5;i++) 
{ 
chopSticks[i]=new Mutex(false); 
} 
for(int i=0;i<5;i++) 
{ 
PhilosopherData pd; 
pd.PhilosopherId=i; 
pd.RightChopStick=chopSticks[(i+1)%5]; 
pd.LeftChopStick=chopSticks[(i+4)%5]; 
pd.AmountToEat=5; 
pd.TotalFood=35; 
p[i]=new Philosopher(pd); 
p[i].MessageArrival+=new Philosopher.MessageArrivedHandler(ShowMessage); 
} 
} 
protected override void Dispose( bool disposing ) 
{ 
if( disposing ) 
{ 
if (components != null) 
{ 
components.Dispose(); 
} 
} 
base.Dispose( disposing ); 
} 
#region Windows Form Designer generated code 
private void InitializeComponent() 
{ 
this.button1 = new System.Windows.Forms.Button(); 
this.listBox1 = new System.Windows.Forms.ListBox(); 
this.SuspendLayout(); 
// 
// button1 
// 
this.button1.Location = new System.Drawing.Point(8, 224); 
this.button1.Name = "button1"; 
this.button1.Size = new System.Drawing.Size(272, 40); 
this.button1.TabIndex = 1; 
this.button1.Text = "Go To Restaurant"; 
this.button1.Click += new System.EventHandler(this.button1_Click); 
// 
// listBox1 
// 
this.listBox1.ItemHeight = 12; 
this.listBox1.Name = "listBox1"; 
this.listBox1.Size = new System.Drawing.Size(296, 220); 
this.listBox1.TabIndex = 2; 
// 
// Form1 
// 
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14); 
this.ClientSize = new System.Drawing.Size(292, 273); 
this.Controls.AddRange(new System.Windows.Forms.Control[] { 
this.listBox1, 
this.button1}); 
this.Name = "Form1"; 
this.Text = "Form1"; 
this.ResumeLayout(false); 
} 
#endregion 
[STAThread] 
static void Main() 
{ 
Application.Run(new Form1()); 
} 
private void button1_Click(object sender, System.EventArgs e) 
{ 
for(int i=0;i<5;i++) 
p[i].Start(); 
} 
public void ShowMessage(object sender,MessageArrivedEventArgs e) 
{ 
switch(e.type) 
{ 
case Philosopher.READY: 
listBox1.Items.Add("Philosopher("+e.philosopherData.PhilosopherId+") ready."); 
break; 
case Philosopher.EATING: 
listBox1.Items.Add("Philosopher("+ 
e.philosopherData.PhilosopherId+") eating "+ 
e.philosopherData.AmountToEat+" of "+ 
e.philosopherData.TotalFood+" food."); 
break; 
case Philosopher.THINKING: 
listBox1.Items.Add("Philosopher("+e.philosopherData.PhilosopherId+") thinking."); 
break; 
case Philosopher.FINISHED: 
listBox1.Items.Add("Philosopher("+e.philosopherData.PhilosopherId+") finished."); 
break; 
} 
} 
} 
} 
//BaseThread.cs----------code:seafrog-------------------------------------------------------- 
using System; 
using System.Threading; 
namespace seafrog.Threading 
{ 
//工作线程抽象类,作为对线程操作的封装。 
public abstract class WorkerThread 
{ 
private object ThreadData; 
private Thread thisThread; 
public object Data 
{ 
get{return ThreadData;} 
set{ThreadData=value;} 
} 
public object IsAlive 
{ 
get{return thisThread==null?false:thisThread.IsAlive;} 
} 
public WorkerThread(object data) 
{ 
this.ThreadData=data; 
} 
public WorkerThread() 
{ 
ThreadData=null; 
} 
public void Start() 
{ 
thisThread=new Thread(new ThreadStart(this.Run)); 
thisThread.Start(); 
} 
public void Stop() 
{ 
thisThread.Abort(); 
while(thisThread.IsAlive); 
thisThread=null; 
} 
protected abstract void Run(); 
} 
} 
//Philosophers.cs----------code:seafrog-------------------------------------------------------- 
using System; 
using System.Threading; 
using seafrog.Threading; 
namespace seafrog.Philosopher 
{ 
//封装哲学家数据的结构 
public struct PhilosopherData 
{ 
public int PhilosopherId; 
public Mutex RightChopStick; 
public Mutex LeftChopStick; 
public int AmountToEat; 
public int TotalFood; 
} 
public class Philosopher : seafrog.Threading.WorkerThread 
{ 
public const int READY=0; 
public const int EATING=1; 
public const int THINKING=2; 
public const int FINISHED=3; 
public Philosopher(object data):base(data){} 
public delegate void MessageArrivedHandler(Object sender,MessageArrivedEventArgs args); 
public event MessageArrivedHandler MessageArrival; 
public static int finished=0; 
protected override void Run() 
{ 
PhilosopherData pd=(PhilosopherData)Data; 
Random r=new Random(pd.PhilosopherId); 
MessageArrival(this,new MessageArrivedEventArgs(READY,pd)); 
WaitHandle[] chopSticks=new WaitHandle[]{pd.LeftChopStick,pd.RightChopStick}; 
while(pd.TotalFood>0) 
{ 
//如果两边的哲学家拿着筷子,则等待。 
WaitHandle.WaitAll(chopSticks); 
//否则,吃饭。 
MessageArrival(this,new MessageArrivedEventArgs(EATING,pd)); 
//把饭吃掉一部分。 
pd.TotalFood-=pd.AmountToEat; 
Thread.Sleep(r.Next(1000,5000)); 
MessageArrival(this,new MessageArrivedEventArgs(THINKING,pd)); 
//放下左边和右边的筷子。 
pd.RightChopStick.ReleaseMutex(); 
pd.LeftChopStick.ReleaseMutex(); 
Thread.Sleep(r.Next(1000,5000)); 
} 
//饭都吃完了。 
MessageArrival(this,new MessageArrivedEventArgs(FINISHED,pd)); 
if(++finished==4) 
System.Windows.Forms.MessageBox.Show("All Finished!"); 
} 
} 
//事件:用来通知主窗体现在哲学家的状态。 
public class MessageArrivedEventArgs : EventArgs 
{ 
public int type; 
public PhilosopherData philosopherData; 
public MessageArrivedEventArgs(int t,PhilosopherData pd) 
{ 
type=t; 
philosopherData=pd; 
} 
} 
} 
<>  
关键词:哲学家就餐问题的C#完成