2016-12-11 6 views
0

ich die sleeping barber problem als Teil meiner Schulaufgabe zu lösen. Es funktioniert gut, wenn ich es mit GDB ausführe, aber bleibt hängen, wenn ich es von der Befehlszeile aus starte. Dies ist der Code:ein Programm in GDB Rennen gibt ein anderes Ergebnis aus einem Programm aus der Befehlszeile

#include <stdio.h> 
#include <semaphore.h> 
#include <pthread.h> 
#include <stdlib.h> 
#define MAX 5 

int nr_clients, open; 
sem_t sem_open1, sem_clients, sem_chair, sem_number; 

void *Barber(){ 
    sem_wait(&sem_open1); 
    printf("Barber: Opening the shop\n"); 
    open = 1; 
    sem_post(&sem_open1); 
    while(1){ 
     printf("Barber: Sleeping while there is no clients\n"); 
     sem_wait(&sem_clients); 
     sem_wait(&sem_number); 
     if(nr_clients > 0){ 
      sem_post(&sem_number); 
      printf("Barber: starting to work on a client\n"); 
      sem_post(&sem_chair); 
      sleep(1); 
      sem_wait(&sem_number); 
      printf("Barber: Client finished\n"); 
      nr_clients--; 
      sem_post(&sem_number); 
     } else { 
      printf("Barber: Closing the shop\n"); 
      break; 
     } 
    } 
} 


void *Client(void *x){ 
    int i = *((int*)x); 
    printf("%8sClient(%d): I want a haircut\n", "", i); 
    sem_wait(&sem_open1); 
    sem_wait(&sem_number); 
    if(open == 1 && nr_clients < MAX){ 
     sem_post(&sem_open1); 
     printf("%8sClient(%d): entering the shop\n", "", i); 
     nr_clients++; 
     sem_post(&sem_number); 
     sem_post(&sem_clients); 
     sem_wait(&sem_chair); 
     printf("%8sClient(%d): barber is working on me\n", "", i); 
    } else { 
     printf("No more room\n"); 
    } 
} 



int main(int argc, char const *argv[]) 
{ 
    if(sem_init(&sem_open1,0,1) == -1 || sem_init(&sem_clients,0,0) == -1 
     || sem_init(&sem_chair,0,0) == -1 || sem_init(&sem_number,0,1) == -1){ 
     printf("ERROR!\n"); 
     return 1; 
    } 

    int nr_threads = 5+1; 

    pthread_t thr_id[nr_threads]; 

    if(pthread_create(&thr_id[0], NULL, Barber, NULL) != 0) { 
     printf("ERROR!\n"); 
     exit(1); 
    } 

    int numbers[nr_threads-1]; 

    for (int i = 0; i < nr_threads-1; ++i) 
    { 
     numbers[i] = i; 
    } 

    for (int i = 1; i < nr_threads; ++i) 
    { 
     if(pthread_create(&thr_id[i], NULL, Client, &numbers[i-1]) != 0){ 
      printf("ERROR!\n"); 
      exit(1); 
     } 
    } 




    sleep(10); 

    sem_wait(&sem_open1); 
    open = 0; 
    sem_post(&sem_open1); 

    sem_post(&sem_clients); 

    for (int i = 0; i < nr_threads; ++i) 
    { 
     pthread_join(thr_id[i], NULL); 
    } 
} 

ich kompilieren Sie es wie folgt aus:

gcc -g sleeping_barber.c -o barber -lpthread 

Und dann ist es nur in der Befehlszeile gestartet werden. Befehlszeile Ausgabe:

 Client(4): I want a haircut 
No more room 
     Client(3): I want a haircut 
     Client(2): I want a haircut 
     Client(1): I want a haircut 
     Client(0): I want a haircut 
^C 

Es wird nur dort stecken.

In GDB Ich laufe es wie folgt aus:

(gdb) file barber 
Reading symbols from barber...done. 
(gdb) r 
Starting program: /home/marko/Desktop/barber 

GDB Ausgang:

[Thread debugging using libthread_db enabled] 
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". 
[New Thread 0x7ffff77f0700 (LWP 2808)] 
Barber: Opening the shop 
Barber: Sleeping while there is no clients 
[New Thread 0x7ffff6fef700 (LWP 2809)] 
     Client(0): I want a haircut 
     Client(0): entering the shop 
Barber: starting to work on a client 
     Client(0): barber is working on me 
[New Thread 0x7ffff67ee700 (LWP 2810)] 
[Thread 0x7ffff6fef700 (LWP 2809) exited] 
     Client(1): I want a haircut 
     Client(1): entering the shop 
[New Thread 0x7ffff5fed700 (LWP 2811)] 
     Client(2): I want a haircut 
     Client(2): entering the shop 
[New Thread 0x7ffff57ec700 (LWP 2812)] 
     Client(3): I want a haircut 
     Client(3): entering the shop 
[New Thread 0x7ffff4feb700 (LWP 2813)] 
     Client(4): I want a haircut 
     Client(4): entering the shop 
Barber: Client finished 
Barber: Sleeping while there is no clients 
Barber: starting to work on a client 
     Client(1): barber is working on me 
[Thread 0x7ffff67ee700 (LWP 2810) exited] 
Barber: Client finished 
Barber: Sleeping while there is no clients 
Barber: starting to work on a client 
     Client(2): barber is working on me 
[Thread 0x7ffff5fed700 (LWP 2811) exited] 
Barber: Client finished 
Barber: Sleeping while there is no clients 
Barber: starting to work on a client 
     Client(3): barber is working on me 
[Thread 0x7ffff57ec700 (LWP 2812) exited] 
Barber: Client finished 
Barber: Sleeping while there is no clients 
Barber: starting to work on a client 
     Client(4): barber is working on me 
[Thread 0x7ffff4feb700 (LWP 2813) exited] 
Barber: Client finished 
Barber: Sleeping while there is no clients 
Barber: Closing the shop 
[Thread 0x7ffff77f0700 (LWP 2808) exited] 
[Inferior 1 (process 2804) exited normally] 

Arbeiten wie in unserer Zuordnung beschrieben.

INFO:

OS -> xubuntu-16.04.1

DEBUGGER -> GNU gdb (Ubuntu 7.11.1-0ubuntu1 ~ 16,04) 7.11.1

+0

Das Programm funktioniert gut für mich. Ubuntu 16.04/gdb 7.11.1/gcc 5.4.0 – gobrewers14

Antwort

2

Sie haben mehrere Probleme in Ihrem Code.

Wenn ein Kunde nicht in den Barber's Shop gelangen kann, geben Sie die Semaphore sem_open1 und sem_client nie wieder frei. Das ist der Grund, warum Ihre Threads offensichtlich blockiert sind und auf sem_open1 warten. Sie können dies abziehen, weil nach "Ich will einen Haarschnitt" nicht mehr ausgegeben wird.

Aber wenn wir am Anfang beginnen, sehen wir, dass open 0 sein muss, wenn der erste Thread den Laden, weil Ihr Zustand eintritt if(open == 1 && nr_clients < MAX) falsch ist. Da noch niemand nr_clients inkrementiert hat, muss es der open Teil sein.

Außerdem können Sie nur auf die Ausgabe aussehen: Der Barbier hat noch nicht den Laden öffnen. Sie könnten etwas Logik hinzufügen, um es erneut zu versuchen, wenn der Laden beim ersten Versuch geschlossen wird.

Der Grund für Ihr Problem ist, dass Sie eine bestimmte Reihenfolge, in der Sie Ihre Threads ausgeführt nehmen. Wie Sie anhand der Thread-Nummer in Ihrer Ausgabe sehen können, ist dies nicht das, was Sie erwartet haben. Sie können sich einfach nicht auf eine Bestellung verlassen.

Um sicherzustellen, dass Ihr Geschäft Sie den Barbers Thread eine Chance geben, müssen geöffnet laufen, bevor Sie die anderen Threads starten. Fügen Sie nach dem Erstellen Ihres Barbers einige sleep() hinzu.

Endlich ... Mit dem, was ich geschrieben habe, Sie zu dem Schluss kommen könnte, dass es alles um Timing ist. Und das Timing kann sehr unterschiedlich sein, wenn Sie Ihr Programm in einem Debugger oder ohne Debugger ausführen.

+0

Danke für die Rückmeldung. Ihr letzter Absatz würde dann die zwei verschiedenen Ergebnisse erklären.Ich denke, wenn ich mit Semaphoren arbeite, wäre die Annahme eines Befehls das letzte, was ich hätte tun sollen. – Marko

+0

Ja, wenn Sie eine bestimmte Reihenfolge sicherstellen können, dann brauchen Sie höchstwahrscheinlich keine Semaphore. ;) Aber Threads laufen ohne Synchronisation und ohne vordefinierte Reihenfolge, wenn Sie keine Maßnahmen ergreifen. – Gerhardh

Verwandte Themen