2016-04-12 16 views
-3

Brauchen Sie Hilfe, wie man den Deadlock für den Code in Schlag, den ich geschrieben habe, verhindert. oder irgendeinen Vorschlag, den ich brauche, um den Code zu reparieren, um Deadlock loszuwerden? auch wenn ich unter Linux laufen habe ich einen Segmentierungsfehler (Core Dumped).Deadlock verhindern

#include <stdio.h> 
#include <stdlib.h> 
#include <stdbool.h> 
#include <pthread.h> 
#include <semaphore.h> 

int cnt; 
int *bites; 
int *old_bites; 
sem_t *sticks; 

void *roger(void *arg) { 
    int rog = *(int*)arg; 

    for(;;) { 
     sem_wait(&(sticks[rog]));    // left 
     sem_wait(&(sticks[(rog + 1) % cnt])); // right 

     bites[rog]++; 

     sem_post(&(sticks[(rog + 1) % cnt])); // right 
     sem_post(&(sticks[rog]));    // left 
} 

pthread_exit(NULL); 

return NULL; 
} 

int main(int argc, char *argv[]) { 

int i; 
pthread_t *rogers; 
int *pos; 
cnt = (int)strtol(argv[1], NULL, 10); 

rogers = (pthread_t *)calloc(cnt, sizeof(pthread_t)); 
pos = (int *)malloc(cnt * sizeof(int)); 
bites = (int *)calloc(cnt, sizeof(int)); 
old_bites = (int *)calloc(cnt, sizeof(int)); 
sticks = (sem_t *)calloc(cnt, sizeof(sem_t)); 

for(i = 0; i < cnt; i++) { 
    sem_init(&(sticks[i]), 0, 1); 
} 

for(i = 0; i < cnt; i++) { 
    pos[i] = i; 
    pthread_create(&(rogers[i]), NULL, roger, (void *)&pos[i]); 
} 

for(;;) { 
    bool dead = true; 
    usleep(50000); 
    for(i = 0; i < cnt; i++) { 
     if(bites[i] != old_bites[i]) { 
      dead = false; 
     } 
    } 
    if(dead) { 
     exit(EXIT_SUCCESS); 
    } 

    for(i = 0; i < cnt; i++) { 
     printf("%8X", bites[i]); 
    } 
    printf("\n"); 
    for(i = 0; i < cnt; i++) { 
     old_bites[i] = bites[i]; 
    } 
} 

for(i = 0; i < cnt; i++) { 
    pthread_join(rogers[i], NULL); 
} 

for(i = 0; i < cnt; i++) { 
    sem_destroy(&(sticks[i])); 
} 

exit(EXIT_SUCCESS); 
} 
+3

SegFault und Deadlock? Vielleicht für die Aufzeichnung gehen und eine Division durch Null hinzufügen? –

+0

OK, ich beiße. Sagen Sie uns, was Sie bisher getan haben, um Ihre App zu debuggen. Welche Linie erhöht den Segfault? –

+0

https://en.wikipedia.org/wiki/Dining_philosophers_problem#Solutions – user3386109

Antwort

0

Ja, ich würde erwarten, dass dies zum Stillstand kommt. Ich weiß nicht, was Sie für cnt verwenden, aber tun wir so, als wäre es 1. In diesem Fall wird nur 1 Thread erstellt. Dieser Thread wird sem_wait(&(sticks[0]));. Dann in der nächsten Zeile wird es sem_wait(&(sticks[(0+1) % 1 == 0]));. Da der Anfangswert Ihrer Semaphore 1 ist, können Sie nicht zweimal auf denselben Semaphor warten, ohne zuerst sem_post. Daher wird dieser Thread für immer auf eine sem_post warten, die es nicht erreichen kann, weil es sem_wait ing ist.

Jetzt betrachten Sie den Fall, wo cnt > 1 (sagen wir einfach cnt == 2, um es einfacher zu machen). Dadurch werden thread0 und thread1 mit 0 und 1 als Argumente für ihre Funktionen erzeugt. Diese Situation könnte passieren:

  • Thread0 führt sem_wait(&(sticks[0]));
  • Kontextschalter: Thread1 sem_wait(&(sticks[1]));
  • führt Thread1 sem_wait(&(sticks[(1+1) % 2 == 0])); // this blocks because thread0 has already sem_wait'ed this semaphore to 0
  • Context Switch ausführt: Thread0 sem_wait(&(sticks[(0+1) % 2 == 1])); // this blocks because thread1 has already sem_wait'ed this semaphore to 0

Nun führt Sie jeden Thread Warte haben für eine sem_post von der anderen, bevor Sie fortfahren können ==> Deadlock. Ich würde erwarten, dass dieses Szenario für steigende Werte von cnt skaliert, obwohl die Situationen, die zu Deadlocks führen würden, komplexer würden.

Warum verwenden Sie 2 Semaphore, um eine einzelne Ressource zu schützen? Diese Theorie klingt falsch für mich. Du verlierst deine Atomizität mit diesem Ansatz (korrigiere mich, wenn ich mich offensichtlich irre).

Außerdem haben Sie eine Race Condition mit Ihrem bites Array. Der Hauptthread beobachtet die Synchronisation nicht, bevor er daraus liest. Dies kann mit dem Seg-Fehler zusammenhängen.

+0

so habe ich segFault behoben, und ist Deadlock-Programm wird nicht enden? und kontinuierlich die Ausgabe ausdrucken? – littlerain

+0

@littlerain Aus dem bereitgestellten Code erwarte ich, dass sich Ihre Worker-Threads letztendlich gegenseitig blockieren. Der gesamte Druckvorgang findet in der Hauptschleife statt, die in eine unendliche "for" -Schleife eintritt und beendet wird, wenn "dead" wahr wird. Das könnte manchmal passieren, vielleicht nicht. Die 'pthread_join' und' sem_destroy' Schleifen werden niemals erreicht. Ich denke, Ihr Array von Semaphoren ist ein logischer Fehler. Du solltest nur eins haben. Wenn Sie auf diese Weise mehr als einen Semaphor verwenden, um eine einzelne Ressource zu schützen ("Bises" -Array), entfernen Sie die Atomizität, auf der die Thread-Synchronisation basiert. – yano