With Mutex and Semaphore in BCL, I simulate the famous "Philosopher Dinner Problem" by writing this piece of C# code (as below), some C# language trick is used, such as "using" syntax and "anonymous method", looks nice? whatever, just for fun..

Code

using System;

using System.Collections.Generic;

using System.Text;

using System.Threading;

 

namespace TestSemaphore

{

    class CriticalSection : IDisposable

    {

        Mutex _mutex;

 

        public CriticalSection(Mutex mutex)

        {

            _mutex = mutex;

        }

 

        public void Enter()

        {

            _mutex.WaitOne();

        }

 

        #region IDisposable Members

 

        public void Dispose()

        {

            _mutex.ReleaseMutex();

        }

 

        #endregion

    }

 

    class PhilosopherSample

    {

        enum State

        {

            Thinking,

            Hungry,

            Eating,

        }

 

        DateTime _endTime = DateTime.Now.AddSeconds(5);

        Random _ran = new Random();

 

        State[] _philosopher = new State[5];

        Semaphore[] _fork = new Semaphore[5];

        Mutex _mutex = new Mutex();

 

        CriticalSection _criticalSection;

 

        public void Run()

        {

            _criticalSection = new CriticalSection(_mutex);

            Do5Times(delegate(int i) { _fork[i] = new Semaphore(0, 1); });

            Do5Times(delegate(int i) { new Thread(Philosopher).Start(i); });

        }

 

        delegate void Action(int i);

 

        void Do5Times(Action ac)

        {

            for (int i = 0; i < 5; i++)

            {

                ac(i);

            }

        }

 

        void Philosopher(object i)

        {

            int id = (int)i;

            while (DateTime.Now < _endTime)

            {

                // take forks

                using (CriticalSection)

                {

                    _philosopher[id] = State.Hungry;

                    Test(id);

                }

                _fork[id].WaitOne();

 

                // eat

                Console.WriteLine("Philosopher " + id + " is eating...");

                Thread.Sleep(_ran.Next(2000));

                ++_count[id];

 

                // put forks

                using (CriticalSection)

                {

                    _philosopher[id] = State.Thinking;

                    Console.WriteLine("Philosopher " + id + " puts forks");

                    Test((id + 4) % 5);

                    Test((id + 1) % 5);

                }

            }

        }

 

        CriticalSection CriticalSection

        {

            get

            {

                _criticalSection.Enter();

                return _criticalSection;

            }

        }

 

        void Test(int id)

        {

            if (_philosopher[id] == State.Hungry && _philosopher[(id + 4) % 5] != State.Eating && _philosopher[(id + 1) % 5] != State.Eating)

            {

                _philosopher[id] = State.Eating;

                _fork[id].Release();

            }

        }


        static void Main(string[] args)

        {

            new PhilosopherSample().Run();

            Console.ReadLine();

        }

    }

}


Posted on 2007-04-01 19:04 Adrian H. 阅读(...) 评论(...) 编辑 收藏