2017-09-25 1 views
0

Der nächste Code druckt normalerweise BA aber manchmal kann es BBAA, BAAB, ... drucken Wie ist es möglich, zwei A oder B damit zu bekommen ?! Dieser Code druckt jedoch nie drei A oder B. Beide Funktionen (produzieren und konsumieren) führen viele Threads aus. Vielen Dank im Voraus.Odd Thread Verhalten

int permission; 
void set_permission(int v) { 
    permission = v; 
    printf("%c", v + 'A');fflush(stdin); 
} 
void* produce(void*) { 
    for (;;) { 
     pthread_mutex_lock(&mr1); 
     set_permission(1); 
     while (permission == 1); 
     pthread_mutex_unlock(&mr1); 
    } 
} 
void* consume(void*) { 
    for (;;) { 
     pthread_mutex_lock(&mr2); 
     while (permission == 0); 
     set_permission(0); 
     pthread_mutex_unlock(&mr2); 
    } 
} 
+5

'fflush (stdin);' bewirkt ein fehlerhaftes Verhalten; Tue es nicht –

+1

Ich sehe 2 nicht verwandte Mutexe. Sieht so aus, als könnten Sie Ihre Synchronisierungsprozeduren entfernen und das gleiche Ergebnis erhalten. –

+0

Was sind die Verweise auf zwei verschiedene Mutex? Wenn der Code versucht, die Variable 'permission' zu schützen, sollten alle Mutex-Referenzen auf den gleichen Mutex verweisen. Vorschlagen: 'for (;;) {while (! Erlaubnis); pthread_mutex_lock (&mr1); set_permission (1); pthread_mutex_unlock (&mr1);} 'der Consumer-Thread würde SEHR ähnlich aussehen und würde den gleichen Mutex verwenden – user3629249

Antwort

4

Ihre Threads sind nicht synchronisiert, da sie nicht denselben Mutex verwenden.

Der andere Thread kann zufällig nur permission auf 1 oder 0 setzen, aber nicht schaffen, Ausgabe noch zu produzieren. In diesem Fall scheint es so, als hätte der erste Thread zwei volle Runden durchlaufen.

Der Schreibvorgang durch den entsprechenden Thread kann auch vollständig verloren, wenn der Speicherinhalt zwischen Kernen synchronisiert und beide Threads schrieb. Der Mutex verhindert dies auch, da er eine strikte Speicherzugriffsreihenfolge festlegt, die, vereinfacht ausgedrückt, garantiert, dass alles, was unter dem Schutz eines Mutex passiert ist, für den nächsten Benutzer des gleichen Mutex vollständig sichtbar ist.

Es wäre sehr unwahrscheinlich, das gleiche Zeichen 3 Mal oder öfter zu drucken, da höchstens ein Schreibvorgang dazwischen stattfindet, also höchstens ein Schreibverlust oder eine Ausgabe in der falschen Reihenfolge. Das ist jedoch nicht garantiert.

Wenn Sie an einem System mit keiner impliziten Speichersynchronisierung arbeiten, könnte Ihr Code auch einen Deadlock auslösen, da die unter einem Mutex ausgeführten Schreibvorgänge niemals an die Benutzer des anderen migrieren. (Dies passiert nicht wirklich, da immer noch eine Synchronisation durch die IO-Operationen eingeführt wird.)

+0

Ich habe printf vor die Zuweisung gestellt und damit alle Doppelzeichen entfernt! Tausend Dank! – vollitwr

+1

@vollitwr Solange Sie nicht den gleichen Mutex verwenden, wird nur die Out-of-Order-Ausgabe eliminiert. Ihr Code ist immer noch anfällig für verlorene Schreibvorgänge, es sei denn, 'Erlaubnis 'ist entweder ein [atomar] (http://de.cppreference.com/w/cpp/atomic/atomic) oder Sie verwenden denselben Mutex. Dieser Fehler ist viel schwieriger zu provozieren, aber es kann immer noch passieren. – Ext3h