2016-06-13 3 views
2

Ich begann an dem Konzept der Semaphoren zu zweifeln; Bitte lesen Sie auch mein Problem zu verstehen ...Bedingung, um sicherzustellen, dass dieses Producer-Consumer-Beispiel nicht blockiert wird?

die manuelle Nach wird sem_post einen Thread entsperren, wenn der Wert der Semaphore größer wird als 0 ... also wenn ich diesen Code:

void* producer(void* arg) 
{ 
    while(1) 
    { 
     sem_wait(&sem_produce); 
     sem_wait(&mutex); 
     // Insert item into buffer 
     sem_post(&mutex); 
     sem_post(&sem_consume); 
    } 
    pthread_exit(NULL); 
} 

void* consumer(void* arg) 
{ 
    while(1) 
    { 
     sem_wait(&sem_consume); 
     sem_wait(&mutex); 
     // Remove item from buffer 
     sem_post(&mutex); 
     sem_post(&sem_produce); 
    } 
    pthread_exit(NULL); 
} 

Wo sem_consume wird mit dem Wert 0 initialisiert, und sem_produce wird mit N initialisiert.

Was passiert, wenn zum Beispiel die N Verbraucher vor Produzenten laufen und versuchen zu konsumieren? Dann sem_consume sollte den Wert -N haben, und wenn dann N Einfügungen, sem_consume und sem_produce beide sollten 0 sein, oder bin ich falsch? Dann bedeutet das, dass die Verbraucher feststecken würden, weil (gemäß der Anleitung) sem_post einen Thread entsperrt, wenn der Wert der Semaphore größer als Null wird ...

Also von dem, was ich aus dem Handbuch verstehe und unter Berücksichtigung des obigen Beispiels, das Dieses Programm funktioniert nur, wenn sem_consume niemals den Wert -N erreicht.

Ich habe Recht? Wenn ja, wie kann ich das Beispiel verbessern, damit es nicht hängen bleibt? Wenn die Antwort nein ist, woran ich mich geirrt habe?

+2

"dann sollte sem_consume den Wert von -N haben". Das kann niemals passieren. Es ist überall in den Semaphor-Handbüchern geschrieben. [sem_overview manual] (http://man7.org/linux/man-pages/man7/sem_overview.7.html) sagt: "Ein Semaphor ist eine ganze Zahl, deren Wert ** niemals unter Null fallen darf **". [sem_wait] (http://man7.org/linux/man-pages/man3/sem_wait.3.html): "Wenn der Semaphor aktuell den Wert Null hat, dann blockt der Aufruf, bis es entweder möglich ist, das Dekrementieren durchzuführen (dh der Semaphorwert steigt über Null), oder ein Signal-Handler unterbricht den Ruf. " – kaylum

+0

Wenn die Konsumenten vor den Produzenten laufen, dann werden die Konsumenten auf "sem_consume" warten, bis ein Produzent es geschafft hat, 'sem_post (& sem_consume)' zu machen, oder? Und nur ein Konsument wird für jeden 'sem_post (& sem_consume)' laufen. Es werden "N" -Elemente in die Warteschlange eingereiht, bevor die Produzenten blockiert werden und auf den Konsum eines Verbrauchers warten. –

+0

Das ist merkwürdig, in meinem parallelen Programmierkurs dachte ich, ich hätte vom Lehrer gehört, dass der Wert eines Semaphors negativ sein könnte und dass dieser negative Wert die Anzahl blockierter Threads darstellen würde. Wenn dieser Wert nicht negativ sein kann, dann habe ich keinen Zweifel. – OiciTrap

Antwort

0

Also von dem, was ich aus dem Handbuch zu verstehen und das oben am Beispiel der einzige Weg, dieses Programm in Ordnung funktionieren würde, wenn sem_consume nie den Wert von N erreichen.

Das ist richtig, Semaphore sind einfach flach, dürfen keine negative Wertperiode sein. Wie von vielen Menschen in den Kommentaren darauf hingewiesen, gibt die Semaphore Handbücher dies deutlich:

A semaphore is an integer whose value is never allowed to fall below zero.

Und:

If the semaphore currently has the value zero, then the call blocks until either it becomes possible to perform the decrement (i.e., the semaphore value rises above zero), or a signal handler interrupts the call.

Und:

Decrementing is a (possibly) blocking function. If the resulting semaphore value is negative, the calling thread or process is blocked, and cannot continue until some other thread or process increments it.

Im Wesentlichen der gesamte Punkt eines Semaphor nur positiv ist, dass, wenn ein Prozess in eine negativen dekrementieren versucht, wird dieser Prozess angehalten, bis ein anderer Prozess hinreichend erhöht es nicht negativ wird wenn der ursprüngliche Prozess dekrementieren darf.

Um Ihren Kommentar:

Das ungerade ist, in meinem parallelen Programmierkurs ich dachte, dass ich vom Lehrer gehörte, dass der Wert einer Semaphore negativ sein könnte und dass dieser negativer Wert die Anzahl der blockierten Threads darstellen würde Wenn dieser Wert nicht negativ sein kann, habe ich keine Zweifel.

Das ist im Wesentlichen was passiert, aber Sie können diesen Wert nicht anzeigen. Wenn Sie versuchen, ein Semaphor zu holen, das momentan nicht positiv ist, wird die Funktion, die versucht, es zu greifen, blockiert, bis es wieder positiv wird.

0

Ich denke, die Definitionen von sem_post und sem_wait sind wie folgt.

sem_wait() Verringert den Wert des Semaphors um eins und wartet, wenn der Wert negativ ist.

sem_post() Erhöht den Wert von Semaphor um eins und wenn ein oder mehrere Threads warten, dann wecken Sie einen.

Daher überprüft sem_post() nicht wirklich, ob der Wert größer als 0 ist oder nicht.

Auch, wenn sem_post() wirklich überprüft, dann kann Semaphor nie als Sperre verwendet werden. Bitte beachten Sie das folgende Code-Snippet.

sem_t m; 
sem_init(&m, 0, 1) 

sem_wait(&m) 
... critical section... 
sem_post(&m) 

Lassen Sie uns sagen, Faden 1 zunächst geplant wird und verringert den Wert auf 0 und tritt in den kritischen Abschnitt. Bevor es vollendet wird, werden drei weitere Threads nacheinander geplant, und jeder von ihnen verringert den Semaphor und die Blöcke weiter. Jetzt wird Thread 1 erneut terminiert, schließt den kritischen Abschnitt ab und ruft sem_post() auf. Mein Punkt ist, dass, wenn es wirklich nach einem positiven Wert sucht, andere Threads nie geplant werden, was nicht der Fall ist. Bitte lassen Sie mich wissen, wenn dies Ihre Frage beantwortet.

Vielen Dank.

Verwandte Themen