哲学家就餐问题的C#实现

来源:互联网 发布:淘宝耳机 编辑:程序博客网 时间:2024/06/05 07:53
<script type="text/javascript"><!--google_ad_client = "pub-2947489232296736";/* 728x15, 创建于 08-4-23MSDN */google_ad_slot = "3624277373";google_ad_width = 728;google_ad_height = 15;//--></script><script type="text/javascript"src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
<script type="text/javascript"><!--google_ad_client = "pub-2947489232296736";/* 160x600, 创建于 08-4-23MSDN */google_ad_slot = "4367022601";google_ad_width = 160;google_ad_height = 600;//--></script><script type="text/javascript"src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>

撰文:周翔

这是我在上操作系统课的那个学期写的一段程序,并组织成了一篇文章。当初被我的挚友曾毅发表在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; } } }

 

( 完)

<script type="text/javascript"><!--google_ad_client = "pub-2947489232296736";/* 728x15, 创建于 08-4-23MSDN */google_ad_slot = "3624277373";google_ad_width = 728;google_ad_height = 15;//--></script><script type="text/javascript"src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
<script type="text/javascript"><!--google_ad_client = "pub-2947489232296736";/* 160x600, 创建于 08-4-23MSDN */google_ad_slot = "4367022601";google_ad_width = 160;google_ad_height = 600;//--></script><script type="text/javascript"src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
原创粉丝点击