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;

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,

}

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...");

++_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();