Wie verhalten sich scanf (), std :: cin in Multithread-Umgebungen?

7

Ich möchte mein Problem anhand eines Beispiels beschreiben.

Angenommen, es gibt ein Array von N /*(N>>1)*/ -Threads, die zum Ausführen dieser Funktion gesetzt sind:

%Vor%

Wenn alle gleichzeitig gestartet sind, was passiert dann? Wie werden gleichzeitige std :: cin-Zugriffe behandelt? Was sieht der Endbenutzer, der auf der Konsole arbeitet,? /?

Bearbeiten: Es gibt noch eine Sache, die ich hinzufügen möchte. Ist der unten stehende Code sicher genug, um die Idee zu verlassen, std: cin nur in einem (wahrscheinlich wichtigsten) Thread zu verwenden?

%Vor%     
diegoperini 17.09.2013, 07:52
quelle

3 Antworten

5

Pre C ++ 11, es hängt von der Implementierung ab; mindestens ein Implementierung garantierte Synchronisation der Anrufe. (VC ++ garantiert die Synchronisation von std::cout , aber nicht für andere Iostream-Objekte. g ++ bietet die gleichen Garantien wie C ++ 11, sogar in früheren Versionen des Compilers.) In C ++ 11 ist es explizit undefiniertes Verhalten.

Die allgemeine Regel ist einfach: jede Änderung des Zustandes eines Objekt in einem Thread erfordert, dass alle Zugriffe synchronisiert werden. Und alle >> Operatoren auf std::istream werden berücksichtigt Ändere seinen Status.

Ganz allgemein ist es für einen bestimmten Stream wahrscheinlich ein guter Richtlinie, um es in nur einem Thread zu verwenden. (Es gibt Ausnahmen, wie das Protokollieren von Streams, bei denen das Protokollierungsobjekt Thread sicherstellt Sicherheit.) Dies gilt insbesondere für die Eingabe, da auch wenn synchronisiert extern, wird die Reihenfolge der Betreiber in der Regel nicht angegeben werden, wenn sie in separaten Threads sind. Damit Auch bei Synchronisierung, wenn Ihr Benutzer "ab" eingibt, was thread bekommt 'a' und das bekommt 'b' in deinem Beispiel unbestimmt.

BEARBEITEN:

Es scheint spezielle Regeln für die Standard-Stream-Objekte zu geben ( std::cin , std::cout usw.). Gleichzeitige Zugriff ist garantiert, dass zumindest in einigen Fällen kein Datenrennen stattfindet. Es kann immer noch dazu führen, dass Charaktere gemischt werden, d. H. Wenn du es bist Eingabe von int (anstelle eines einzelnen Zeichens) und Ihres Benutzers Eingaben "123 89\n" , es gibt eine Möglichkeit, die Thread 1 sehen wird "1389\n" , und thread 2 "2 " , was Ihnen keinen Zusammenhang gibt Ergebnisse.

Meine globale Empfehlung steht. Ich kann mir keine realistische vorstellen Fall, in dem das Interleaving von Zeichen nicht erzeugt würde ein Problem. (Ich glaube auch nicht, dass ich jemals Code geschrieben habe, der ... tatsächlich Eingaben von std::cin ; es ist immer von einem std::istream& was möglicherweise std::cin ist, oder könnte sein eine Datei.)

    
James Kanze 17.09.2013, 08:26
quelle
9

Ich würde sagen, das Ergebnis ist ohne Mutexe nicht vorhersehbar.

Wenn Sie einen Mutex verwenden, ist alles in Ordnung. Dafür sind Mutexe da.

    
Konstantin 17.09.2013 08:04
quelle
5

Der erste Thread verwendet std :: cin sperrt es (es sei denn, Sie use sync_with_stdio(false) ). Du brauchst also keinen Mutex. Ссылка Trotzdem empfehle ich nicht, es in Multi-Thread-Anwendungen zu verwenden. Das Problem ist, dass es keine Möglichkeit gibt, die Eingabe von cin von einem anderen Thread zu unterbrechen.

    
Ivan Ishchenko 17.09.2013 08:13
quelle

Tags und Links