Решение задачи в программных кодах
Программный код приложения «Философ»
//Основной код работы философа
while (true)
{//значение семафора: 1 - философ ест, 2 - гуляет, 3- гуляет и голоден
walk();
WaitForSingleObject(mutex, INFINITI); //ожидание мьютекса на палочки
fixed (uint* adr_sticks = &sticks)
{ ReleaseSemaphore(SemathorSticks, 1, adr_sticks); } //считывем количество палочек
WaitForSingleObject(SemathorSticks, INFINITI);
if (sticks >= 2) //при истиности условия
{
WaitForSingleObject(SemathorSticks, INFINITI);
WaitForSingleObject(SemathorSticks, INFINITI);
//уменьшаем на 2 палочки
ReleaseMutex(mutex); //отпускаем мьютекс - палочки
eating();
}
else
{// если не хватает палочек, философ уходит гулять голодным
ReleaseMutex(mutex);
WaitForSingleObject(Philmutex, INFINITI);
if(MyState != "Walking and Hungry")
ReleaseSemaphore(SemathorState, 1, null);
MyState = "Walking and Hungry";
ReleaseMutex(Philmutex);
label.Invoke(new Action(() => { label.Text = "Philosopher " + number.ToString() + ": " + MyState; }));
}
}
}
public void walk()
{
Thread.Sleep(rand.Next(2500,3000));
}
public void eating()
{//уведомляем сервер о состоянии eating
WaitForSingleObject(Philmutex, INFINITI);
if (MyState == "Walking") //переводим в состояние "ем" //семафор состояния
{
WaitForSingleObject(SemathorState, INFINITI);
}
else
if (MyState == "Walking and Hungry")
{ //если до того как поесть, философ был "Walking and Hungry" //уменьшаем семафор с 3 до 1
WaitForSingleObject(SemathorState, INFINITI);
WaitForSingleObject(SemathorState, INFINITI);
}
ReleaseMutex(Philmutex);
MyState = "Eating";
label.Invoke(new Action(() => { label.Text = "Philosopher " + number.ToString() + ": " + MyState; }));
Thread.Sleep(rand.Next(3000, 4000));
WaitForSingleObject(mutex, INFINITI);
WaitForSingleObject(Philmutex, INFINITI);
ReleaseSemaphore(SemathorSticks, 2, null);
//после того как поел, философ возвращает палочки
ReleaseSemaphore(SemathorState, 1, null);
//и переходит в состояние «гуляю»
MyState = "Walking";
ReleaseMutex(Philmutex);
ReleaseMutex(mutex);
label.Invoke(new Action(() => { label.Text = "Philosopher " + number.ToString() + ": " + MyState; }));
}
Программный код приложения «Стол»
for (int i = 0; i < count; i++)
{
//создание процессов «Философ»
pInfo[i] = new PROCESS_INFORMATION();
Sleep(500);
bool retValue = CreateProcess(null, CommandLine,
ref pSec, ref tSec, false, 0, IntPtr.Zero, null, ref sInfo, out pInfo[i]);
}
del_Monitoring = new Del_clientFunction(Monitoring); //Запуск процесса мониторинга статусов философов
hThread = StartThread(del_Monitoring);
//Основной код для работы с философами
while (true)
{
for (int i = 0; i < Philosophers; i++)
{//пробегаем по каждому семафору состояния философа и считываем его значение
WaitForSingleObject(PhilMutex[i], 30);//захват мьютекса для доступа к состоянию
fixed (uint* adr_state = &state)
{ReleaseSemaphore(SemathorStates[i], 1, adr_state); };
WaitForSingleObject(SemathorStates[i], 1 );
//считывание состояния
switch (state)
{
case 1: // если ест
if (predstate[i] == 1) break; //если до этого ел, то //выходим из цикла
for (int j = 0; j < Philosophers / 2; j++) //ищем свободное //место
{
if (placesFlag[j] == true)
{
placesFlag[j] = false; //занимаем место
myPlace[i] = j; //философ запоминает свое место
predstate[i] = 1; //предыдущее состояние //устанавливаем "ем"
break;
}
}
break;
case 2: //если гуляет
if (predstate[i] == 2) break; //если до этого гулял, выходим из цикла
if (predstate[i] == 1) //если раньше ел
{
placesFlag[myPlace[i]] = true; //освобождаем свое место
predstate[i] = 2; //предыдущее состояние устанавливаем "гуляю"
break;
}
break;
case 3: //если состояние "голодный и гуляю"
if (predstate[i] == 3) break;
{
predstate[i] = 3; // предыдущее состояние устанавлием "голоден и гуляю"
}
break;
}
ReleaseMutex(PhilMutex[i]);
}
}
}
//уничтожение процессов
public void Terminate()
{
for (int i = 0; i < Philosophers; i++)
TerminateProcess(pInfo[i].hProcess, 0);
TerminateProcess(GetCurrentProcess(), 0);
}
Пример работы программы
Рисунок 4.
Рисунок 5.
Рисунок 6.