Parkhaus mit Semaphore absichern

Kirby.exe

Top Contributor
Also wir haben ein basis Programm gegeben und sollen mit Semaphore dafür sorgen, dass der kritische Bereich gehandled wird.

Meiner Meinung nach ist der kritische Bereich z.B. das ein oder ausfahren beim Parkhaus. Weitere sind mir nicht eingefallen xD

Hier ist das Base-Code:
C:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

#define AUTOS 500
#define PLATZ 100
#define TIME 4

// gemeinsame Variablen
pthread_t th[AUTOS];
pthread_t infoID;
int parkplaetze[PLATZ];
int anzahl = 0;

// Thread-Funktion - Autos
void* auto_thread()
{
   // Zufallszahlengenerator initialisieren
   srand((unsigned) pthread_self());

   while(1) {
      if(anzahl < PLATZ) {  // Es ist noch Platz im Parkhaus
            anzahl++;

         // Platz waehlen   
         int pn = 0;
            while (parkplaetze[pn] != 0) {
                pn = rand() % PLATZ;
           }
          parkplaetze[pn] = 1;

          // Parken
            int ri = rand();
            sleep(ri % TIME + 1);

      // Parkhaus verlassen         
       parkplaetze[pn] = 0;
        anzahl--;

         pthread_exit(NULL);
   }
 }
}



void* info (void *name) {
   int j,k;

   while(1) {
       for(j = 0; j < PLATZ; j++) {
              if(parkplaetze[j] != 0) {
                  printf("X");
              }else{
                  printf("-");
              }
       }
      printf("\n");
        printf("Anzahl der freien Plätze im Parkhaus: %3d \n\n", PLATZ-anzahl);

      // sleep(1);
   }
}


int main() {
  int i = 0;

    // Alle Parkplaetze sind am Anfang leer
    for(i = 0; i < PLATZ; i++) {
        parkplaetze[i] = 0;
    }
    
    // Thread mit Info-Anzeige starten
   pthread_create(&infoID,NULL, info, NULL);

    // Autos starten
    for(i = 0; i < AUTOS; i++)    {
          if(pthread_create(&th[i],NULL, auto_thread, NULL))
            {   fprintf(stderr, "  Fehler beim Erzeugen des Threads %d\n", i);
               return(0);
            }
    }

    // Warten bis alle Autos das Parkhaus verlassen haben
    for(i = 0; i < AUTOS; i++) {
          pthread_join(th[i], NULL);
    }

    printf("Alle Autos haben das Parkhaus verlassen.\n");
  return 0;
}

Und hier ist meine leicht angepasste Version:
C:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>

#define AUTOS 500
#define PLATZ 100
#define TIME 4

// gemeinsame Variablen
pthread_t th[AUTOS];
pthread_t infoID;
int parkplaetze[PLATZ];
int anzahl = 0;
sem_t manager;


// Thread-Funktion - Autos
void* auto_thread(){

    // Zufallszahlengenerator initialisieren
    srand((unsigned) pthread_self());

    sem_wait(&manager);
    anzahl++;

    // Platz waehlen   
    int pn = 0;
    while (parkplaetze[pn] != 0) {
        pn = rand() % PLATZ;
    }
    parkplaetze[pn] = 1;

    // Parken
    int ri = rand();
    sleep(ri % TIME + 1);

    // Parkhaus verlassen       
    sem_post(&manager); 
    parkplaetze[pn] = 0;
    anzahl--;
    pthread_exit(NULL);
}



void* info (void *name) {
   int j,k;

   while(1) {
       for(j = 0; j < PLATZ; j++) {
              if(parkplaetze[j] != 0) {
                  printf("X");
              }else{
                  printf("-");
              }
       }
      printf("\n");
        printf("Anzahl der freien Plätze im Parkhaus: %3d \n\n", PLATZ-anzahl);

      // sleep(1);
   }
}


int main() {
    int i = 0;

    // Alle Parkplaetze sind am Anfang leer
    for(i = 0; i < PLATZ; i++) {
        parkplaetze[i] = 0;
    }
    //Initilize Semaphore for ParkManagement
    sem_init(&manager, 0, 100);

    // Thread mit Info-Anzeige starten
    pthread_create(&infoID,NULL, info, NULL);

    // Autos starten
    for(i = 0; i < AUTOS; i++)    {
          if(pthread_create(&th[i],NULL, auto_thread, NULL)){   
            fprintf(stderr, "  Fehler beim Erzeugen des Threads %d\n", i);
            return(0);
        }   
    }

    // Warten bis alle Autos das Parkhaus verlassen haben
    for(i = 0; i < AUTOS; i++) {
          pthread_join(th[i], NULL);
    }

    printf("Alle Autos haben das Parkhaus verlassen.\n");
    return 0;
}
 
K

kneitzel

Gast
Beim Verlassen musst Du erst verlassen und dann Freigeben. Aber Du gibst erst frei und dann machst Du die Änderungen. Das fällt etwas auf.

Und auto_thread braucht einen void * Parameter, sonst übersetzt es sich zumindest bei mir nicht.

Und dann hast Du bis zu 100 Threads, die ein increment / decrement auf einer Variable machen oder auf ein Array zugreifen / Werte setzen ....
Das halte ich für nicht wirklich Zielführend :)

Aber ich hatte auch Läufe, die sehr erstaunlich waren von wegen Ausgabe. Da hat alles recht gut geklappt. Eigentlich erstaunlich ...
 

Kirby.exe

Top Contributor
Also ich vermute auch mal der zugriff auf das Array mittels der Variable "pn" ist sehr kritisch, da sie ja von einem neueren Thread neuzugewiesen wird oder? :)

Edit: Ich hatte jetzt nur zwei Mutex-Semaphore eingefügt :) Es wird etwas besser und am ende wird auch die richtige Anzahl an freien Plätzen angezeigt, aber er beginnt dennoch am anfang bei -400

C:
void* auto_thread(){

    // Zufallszahlengenerator initialisieren
    srand((unsigned) pthread_self());

    sem_wait(&manager);
    sem_wait(&enterSpace);
    // Platz waehlen
    anzahl++;
    int pn = 0;
    while (parkplaetze[pn] != 0) {
        pn = rand() % PLATZ;
    }
    parkplaetze[pn] = 1;
    sem_post(&enterSpace);

    // Parken
    int ri = rand();
    sleep(ri % TIME + 1);

    // Parkhaus verlassen 
    sem_wait(&leaveSpace);     
    parkplaetze[pn] = 0;
    anzahl--;
    sem_post(&leaveSpace);
    sem_post(&manager); 
    
    pthread_exit(NULL);
}
 
K

kneitzel

Gast
Also was für Semaphoren hast Du da eingefügt? Was genau machst du da?
Und beide bearbeiten die gleichen Variablen ... Gleichzeitige Zugriffe schließt du somit nicht wirklich aus.
 

Kirby.exe

Top Contributor
Also was für Semaphoren hast Du da eingefügt? Was genau machst du da?
Und beide bearbeiten die gleichen Variablen ... Gleichzeitige Zugriffe schließt du somit nicht wirklich aus.
Also ich versuche zumindest die inkrementierung und die dekrementierung von anzahl durch zwei Mutex Semaphores zu splitten aber mit der Variable wüsste ich nicht wie ich das sonst machen könnte
 

mrBrown

Super-Moderator
Mitarbeiter
Einfachste Regel: pro logischer Zustand ein Mutex, nicht pro Änderung ein einzelner :)
In deinem Fall gibt es einen Zustand (parkplaetze und anzahl zusammen), also auch nur einen einzelnen Mutex, der dann für jede Änderung benutzt wird.

Allerdings ist das ganze für den Anwendungsfall etwas tricky, vielleicht willst du deine Idee, die du versucht hast umzusetzen, erst einmal beschreiben?
 

Kirby.exe

Top Contributor
Allerdings ist das ganze für den Anwendungsfall etwas tricky, vielleicht willst du deine Idee, die du versucht hast umzusetzen, erst einmal beschreiben?
Naja also ich hatte mir gedacht, dass ich die while(true) erstmal durch ein Semaphore ersetze um das busy wait wegzubekommen :) Nun muss man noch das ein und ausfahren handlen und da ist halt das problem, dass man die selbe variable für das ein und ausfahren hat. Man könnte doch die Variable kopieren und somit einen fehlerhaften array zugriff verhindern oder ?
 

mihe7

Top Contributor
Also meiner Meinung nach, ist @Kirby_Sike durchaus auf dem richtigen Weg. Es gibt einmal das Parkhaus als Ressource als Ganzes. Mit einem Semaphore, der die Zahl der freien Parkplätze widerspiegelt, wird also verhindert, dass nicht mehr Fahrzeuge einfahren können als an Plätzen zur Verfügung steht. Dieser Semaphore muss also den Bereich des Einfahrens abdecken - ausfahren kann man zu jeder Zeit.

Der zweite m. E. notwendige Semaphore ist ein binärer (Mutex), um den Variablen-Zugriff zu schützen. Mit diesem wird das Ein- und Ausfahren abgesichert.
 
Zuletzt bearbeitet:
Ähnliche Java Themen

Ähnliche Java Themen

Neue Themen


Oben