Salve a tutti, sono alle prese con i thread ed ultimamente sto battendo la testa sull'implementazione del problema dei filosofi a cena (comunicazione
tra processi). Per capirci, ho implementato la non-soluzione del problema (avete presente
il testo del Tanenbaum,I moderni Sistemi Opeartivi), ossia quella in cui sorge il problema
se i filosofi (i thread) partono contemporaneamente per l'accesso delle forchette (le risorse)
per mangiare.Qualcuno di voi ha mai implementato la soluzione del Tanenbaum in C?
Ho fatto questa, ma non mi funziona, subito mi esce da tutti i thread:
codice:
#include <windows.h>
#include <process.h> /* _beginthread, _endthread */
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#define N 5 //numero di filosofi
#define LEFT (c-1)%N //numero del vicino di sinistra
#define RIGHT (c+1)%N //numero del vicino di destra
#define THINKING 0 //filosofo pensante
#define HUNGRY 1 //filosofo affamato
#define EATING 2 //filosofo che mangia
HANDLE hforchetta[N]; //l'array di semafori
HANDLE hMutex; //Per la mutua esclusione
int vmang[N]; //numero di volte che ogni filosofo mangia
int stato[N]; //vettore per tenere traccia dello stato di ogni filosofo(mangiano,pensano o sono affamati)
int c; //filosofo
int fine=0;
/*Funzioni necessarie al problema*/
void Filosofi(void *ch);
void prendiFork(int c); //c: quale filosofo da 0 a N-1
void lasciaFork(int c);
void test(int c); //per testare lo stato dei filosofi vicini a chi vuole mangiare
void pensa(void);
void mangia(void);
int main()
{
hMutex=CreateMutex(NULL,false,"mutex");
for (int i=0;i<N;i++)
{
hforchetta[i] = CreateSemaphore(NULL, 1,1,NULL);
vmang[N]=0; //nessun filosofo ha ancora mangiato
}
printf(" Digita un tasto per Uscire \n");
int namefilo[N];
for ( i=0;i<N;i++)
{
namefilo[i]=i; //filosofo0=0, filosofo1=1.....
_beginthread( Filosofi, 0, (void *) &namefilo[i]);
}
getch();
for ( i=0;i<N;i++)
{
printf("Il filosofo %d ha mangiato %d volte\n",i+1,vmang[i]);
CloseHandle(hforchetta[i]);
}
CloseHandle(hMutex);
fine=1;
return 0;
}
/////////////////
void Filosofi(void *ch)
{
/*Tutto questo lavoro per convertire ch (puntatore ad un void) in un intero*/
int *b;
b=(int *)ch;
c=*b; //in c mettiamo il contenuto di b
/*Bastava scrivere c=*((int *)ch); per compiere lo stesso lavoro delle 3 righe sopra*/
while(fine==0)
{
pensa();
prendiFork(c);
lasciaFork(c);
}
_endthread();
}
void prendiFork(int c) //prende le forchette ed eventualmente mangia
{
DWORD risMut;
risMut=WaitForSingleObject(hMutex,INFINITE);
switch (risMut)
{
case WAIT_OBJECT_0:
stato[c]=HUNGRY;
test(c);
ReleaseMutex(hMutex);
//Si blocca se le forchette non sono state ottenute
DWORD risForkD,risForkS;
risForkD=WaitForSingleObject(hforchetta[RIGHT],INFINITE);
if (risForkD==WAIT_OBJECT_0)
{
printf("il filosofo %d ha preso la forchetta destra \n",c+1);
risForkS=WaitForSingleObject(hforchetta[LEFT], INFINITE);
if (risForkS==WAIT_OBJECT_0)
{
printf("il filosofo %d ha preso anche la forchetta sinistra e inizia a mangiare\n",c+1);
mangia();
}
else
{
ReleaseSemaphore(hforchetta[RIGHT],1,NULL);
printf("il filosofo %d si e' stancato di aspettare la sinistra e lascia la destra \n",c+1);
}
break;
}
}
}
void lasciaFork(int c)
{
DWORD risMut;
risMut=WaitForSingleObject(hMutex,INFINITE);
switch (risMut)
{
case WAIT_OBJECT_0:
printf("il filosofo %d sta per smetter di mangiare (lascia le forchette)\n",c+1);
ReleaseSemaphore(hforchetta[LEFT],1,NULL);
ReleaseSemaphore(hforchetta[RIGHT],1,NULL);
printf("il filosofo %d sta iniziando a pensare\n",c+1);
Sleep(2000); stato[c]=THINKING; //il filosofo pensa
test(LEFT);
test(RIGHT);
ReleaseMutex(hMutex);
break;
}
}
void test(int c)
{
if ((stato[c]==HUNGRY) && (stato[LEFT]!=EATING) && (stato[RIGHT]!=EATING))
{
stato[c]=EATING;
ReleaseSemaphore(hforchetta[c],1,NULL);
}
}
void pensa()
{
printf("Il filosofo %d sta pensando in attesa delle forchette...",c+1);
stato[c] = THINKING;
Sleep(1000);
}
void mangia()
{
stato[c] = EATING;
vmang[c]++; //vmang[c]=vmang[c]+1;
Sleep(2000); //il filosofo mangia
}