E
Hy.
Ich hatte die Aufgabe das 4-Philosophen Problem zu lösen und habe dazu ein kleines Programm geschrieben:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <pthread.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#define LOOP_SIZE 10
#define LOOP_END 100
#define KEYSHM 600
#define KEYSEM1 22
int semid; // global für alle threads
/******************************************************************************
* pthread_sleep takes an integer number of seconds to pause the current thread
* We provide this function because one does not exist in the standard pthreads
* library. We simply use a function that has a timeout.
*****************************************************************************/
int pthread_sleep (int seconds) {
pthread_mutex_t mutex;
pthread_cond_t conditionvar;
struct timespec timetoexpire;
if (pthread_mutex_init (&mutex, NULL))
return -1;
if (pthread_cond_init (&conditionvar, NULL))
return -1;
timetoexpire.tv_sec = (unsigned int) time (NULL) + seconds;
timetoexpire.tv_nsec = 0;
return pthread_cond_timedwait (&conditionvar, &mutex, &timetoexpire);
}
void *Thread1 (void *s) { // Philosoph 1
struct sembuf poperation[2],
voperation[2],
woperation[2];
poperation[0].sem_op = -1;
poperation[0].sem_num = 0; // Semaphore-Array
poperation[0].sem_flg = 0;
voperation[0].sem_op = 1;
voperation[0].sem_num = 0;
voperation[0].sem_flg = 0;
woperation[0].sem_op = 0; // Zustzäliche Warte-Operation = 0
woperation[0].sem_num = 0;
woperation[0].sem_flg = 0;
poperation[1].sem_op = -1;
poperation[1].sem_num = 1;
poperation[1].sem_flg = 0;
voperation[1].sem_op = 1;
voperation[1].sem_num = 1;
voperation[1].sem_flg = 0;
woperation[1].sem_op = 0;
woperation[1].sem_num = 1;
woperation[1].sem_flg = 0;
if ((semid = semget (KEYSEM1, 4, 0600|IPC_CREAT)) == -1) {
perror ("1 semget: semget failed");
exit (1);
}
semctl (semid, 0, SETALL, 0);
while (1) {
printf ("A: moechte Essen ..\n");
semop (semid, woperation, 2); // warte auf Freigabe
printf ("A: == isst ==\n");
semop (semid, voperation, 2); // belege
pthread_sleep (1);
semop (semid, poperation, 2); // gibt frei
printf ("A: denkt ..\n");
pthread_sleep (1);
}
semctl (semid, 0, IPC_RMID, 0);
}
void *Thread2 (void *s) { // Philosoph 2
struct sembuf poperation[2],
voperation[2],
woperation[2];
poperation[0].sem_op = -1;
poperation[0].sem_num = 1;
poperation[0].sem_flg = 0;
voperation[0].sem_op = 1;
voperation[0].sem_num = 1;
voperation[0].sem_flg = 0;
woperation[0].sem_op = 0;
woperation[0].sem_num = 1;
woperation[0].sem_flg = 0;
poperation[1].sem_op = -1;
poperation[1].sem_num = 2;
poperation[1].sem_flg = 0;
voperation[1].sem_op = 1;
voperation[1].sem_num = 2;
voperation[1].sem_flg = 0;
woperation[1].sem_op = 0;
woperation[1].sem_num = 2;
woperation[1].sem_flg = 0;
while (semid == -1) // warte Anfangs
usleep (100000);
while (1) {
printf ("B: moechte Essen ..\n");
semop (semid, woperation, 2);
printf ("B: == isst ==\n");
semop (semid, voperation, 2);
pthread_sleep (1);
semop (semid, poperation, 2);
printf ("B: denkt ..\n");
pthread_sleep (2);
}
}
void *Thread3 (void *s) { // Philosoph 3
struct sembuf poperation[2],
voperation[2],
woperation[2];
poperation[0].sem_op = -1;
poperation[0].sem_num = 2;
poperation[0].sem_flg = 0;
voperation[0].sem_op = 1;
voperation[0].sem_num = 2;
voperation[0].sem_flg = 0;
woperation[0].sem_op = 0;
woperation[0].sem_num = 2;
woperation[0].sem_flg = 0;
poperation[1].sem_op = -1;
poperation[1].sem_num = 3;
poperation[1].sem_flg = 0;
voperation[1].sem_op = 1;
voperation[1].sem_num = 3;
voperation[1].sem_flg = 0;
woperation[1].sem_op = 0;
woperation[1].sem_num = 3;
woperation[1].sem_flg = 0;
while (semid == -1) // warte Anfangs
usleep (100000);
while (1) {
printf ("C: moechte Essen ..\n");
semop (semid, woperation, 2);
printf ("C: == isst ==\n");
semop (semid, voperation, 2);
pthread_sleep (2);
semop (semid, poperation, 2);
printf ("C: denkt ..\n");
pthread_sleep (1);
}
}
void *Thread4 (void *s) { // Philosoph 4
struct sembuf poperation[2],
voperation[2],
woperation[2];
poperation[0].sem_op = -1;
poperation[0].sem_num = 0;
poperation[0].sem_flg = 0;
voperation[0].sem_op = 1;
voperation[0].sem_num = 0;
voperation[0].sem_flg = 0;
woperation[0].sem_op = 0;
woperation[0].sem_num = 0;
woperation[0].sem_flg = 0;
poperation[1].sem_op = -1;
poperation[1].sem_num = 3;
poperation[1].sem_flg = 0;
voperation[1].sem_op = 1;
voperation[1].sem_num = 3;
voperation[1].sem_flg = 0;
woperation[1].sem_op = 0;
woperation[1].sem_num = 3;
woperation[1].sem_flg = 0;
while (semid == -1) // warte Anfangs
usleep (100000);
while (1) {
printf ("D: moechte Essen ..\n");
semop (semid, woperation, 2);
printf ("D: == isst ==\n");
semop (semid, voperation, 2);
pthread_sleep (2);
semop (semid, poperation, 2);
printf ("D: denkt ..\n");
pthread_sleep (2);
}
}
int main (void) {
pthread_t tid1,
tid2,
tid3,
tid4;
pthread_create (&tid1, NULL, Thread1, (void *) NULL); // erzeuge Philosophen
pthread_create (&tid2, NULL, Thread2, (void *) NULL);
pthread_create (&tid3, NULL, Thread3, (void *) NULL);
pthread_create (&tid4, NULL, Thread4, (void *) NULL);
pthread_join (tid1, NULL);
pthread_join (tid2, NULL);
pthread_join (tid3, NULL);
pthread_join (tid4, NULL);
return 0;
}
Wie man sehen kann, habe ich das ganze mit 4 einzelnen Threads realisiert. Um das ganze hinzubekommen, habe ich neben der p & v Operation noch eine dritte 'Wait for Zero' Operation eingeführt.
Mein Prof will mir das Programm aber nicht abnehmen, da er meint, es könnte dazu kommen, dass alle 4 somit gleichzeitig essen, wenn eine zu große Pause zw der P und W Operation liegt. Irgendwie ist mir das so halb klar geworden, aber ich weiß einfach nicht, wie ich meine zusätzliche W-Operation unbrauchbar machen kann.
Kann mir evtl. jemand kurz erklären, wie ich auf diese Verzichten kann und das im Code umsetze? Irgendwie ist mir wohl was noch nicht klar geworden. Ich hock jetzt schon ein Weilchen davor und glaube langsam den Wald vor Bäumen nicht mehr zu sehen
Ein bisschen Unterstützung wäre echt Super