C ++ Thread, gemeinsame Daten
Ich habe eine Anwendung, wo 2 threads ausgeführt werden... Ist es certanty, dass, wenn ich eine Globale variable aus einem thread, die andere bemerken diese Veränderung?
Ich habe keine syncronization oder Gegenseitigen Ausschluss-system an Ort und Stelle... aber sollte dieser code die ganze Zeit arbeiten (stellen Sie sich eine Globale bool namens dataUpdated):
Thread 1:
while(1) {
if (dataUpdated)
updateScreen();
doSomethingElse();
}
Thread 2:
while(1) {
if (doSomething())
dataUpdated = TRUE;
}
Funktioniert ein compiler wie gcc optimieren Sie diesen code in einer Weise, dass es nicht überprüfen Sie für den globalen Wert, nur wenn man es mit dem Wert zur compile-Zeit (weil es in nevers geändert an der gleichen thred)?
PS: Wird diese für ein Spiel-ähnliche Anwendung, es wirklich spielt keine Rolle, ob es eine zu Lesen, während der Wert geschrieben wird... alles was zählt ist, dass die Veränderung wird bemerkt, von den anderen thread.
InformationsquelleAutor der Frage fabiopedrosa | 2008-09-22
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ja. Nein. Vielleicht.
Erste, wie andere erwähnt haben, die Sie brauchen, um machen dataUpdated flüchtig; sonst der compiler kann frei sein, zu heben, es zu Lesen aus der Schleife heraus (je nachdem, ob oder nicht Sie es sehen können, dass doSomethingElse nicht berühren).
Zweitens, je nach Prozessor und Bestellung muss, möglicherweise müssen Sie Speicher Barrieren. volatile ist genug, um Garantie, dass der andere Prozessor die Veränderung sehen, die irgendwann, aber nicht genug, um Garantie, dass die änderungen gesehen werden, in der Reihenfolge, wie Sie durchgeführt wurden. Dein Beispiel hat nur ein flag, so dass es nicht wirklich zeigen diese Phänomene. Wenn Sie brauchen, und verwenden Sie memory-Barrieren, Sie sollten nicht mehr benötigen, flüchtige
Flüchtig betrachtet schädlich und Linux-Kernel-Memory-Barrieren sind gute Hintergrundinformationen über die zugrunde liegenden Probleme; ich weiß wirklich nicht, etwas ähnliches geschrieben, speziell zum Gewindeschneiden. Zum Glück threads nicht diese vorbringen annähernd so oft wie die hardware-Peripherie, wenn auch die Art von Fall, dass Sie beschreiben (ein flag, das anzeigt, Fertigstellung, mit anderen Daten ausgegangen werden gültig, wenn das flag gesetzt ist) ist genau die Art von Sache, wo die Bestellung matterns...
InformationsquelleAutor der Antwort puetzk
Hier ist ein Beispiel-boost-condition-Variablen:
InformationsquelleAutor der Antwort 1800 INFORMATION
Verwenden Sie ein Schloss. Immer verwenden Sie immer ein Schloss, um den Zugriff auf freigegebene Daten. Markieren Sie die variable als volatile wird verhindern, dass der compiler aus der Optimierung entfernt den Speicher gelesen, aber nicht verhindern, dass andere Probleme wie Speicher re-Bestellung. Ohne sperren gibt es keine Garantie, dass der Speicher schreibt in doSomething() wird sichtbar in den updateScreen () - Funktion.
Die einzige andere sichere Möglichkeit ist die Verwendung eines Speicher Zaunentweder explizit oder implizit durch ein eng verzahntes* Funktion zum Beispiel.
InformationsquelleAutor der Antwort Niall
Verwenden Sie die flüchtigen Schlüsselwort Hinweis an den compiler, dass der Wert jederzeit ändern kann.
Den oben garantieren, dass jeder Zugriff auf die variable zu und aus der Erinnerung ohne konkrete Optimierungen und als Ergebnis alle threads auf den gleichen Prozessor "siehe" änderungen an der Variablen mit der gleichen Semantik wie der code lautet.
Chris Jester-Jung wies darauf hin, dass die Kohärenz betrifft, um eine solche variable Wert ändern, die entstehen können in einer multi-Prozessor-Systeme. Dies ist eine überlegung, und es hängt von der Plattform ab.
Tatsächlich, es sind wirklich zwei überlegungen zu denken, die relativ zu der Plattform. Sie sind kohärent und Unteilbarkeit der Speicher-Transaktionen.
Atomarität ist tatsächlich eine Gegenleistung für single-und multi-Prozessor-Plattformen. Das Problem entsteht, weil die variable wird wahrscheinlich multi-byte in der Natur und die Frage ist, ob ein thread sehen konnte, eine teilweise änderung der Wert-oder nicht. ie: Einige bytes geändert, Kontext wechseln, Ungültiger Wert Lesen durch Unterbrechung thread. Für eine einzige variable, bei der die Natürliche Maschine, Wort Größe oder kleiner und natürlich ausgerichtet, sollte nicht von Belang sein. Insbesondere eine int Typ sollte immer OK in dieser Hinsicht, wie lange, wie es ausgerichtet ist - das sollte standardmäßig der Fall für den compiler.
Relation zu Kohärenz, hier ist eine mögliche Besorgnis, die in einem multi-Prozessor-system. Die Frage ist, ob das system implementiert vollständige cache-Kohärenz-oder nicht zwischen den Prozessoren. Wenn Sie umgesetzt werden, dies erfolgt in der Regel mit dem MESI-Protokoll in der hardware. Die Frage hat nicht state-Plattformen, aber sowohl die Intel-x86-Plattformen und PowerPC-Plattformen sind cache-kohärent über Prozessoren für die in der Regel zugeordneten Programmdaten Regionen. Deshalb ist diese Art von Problem sollte nicht ein Problem für gewöhnliche Daten-Speicher-Zugriffe von threads, auch wenn es mehrere Prozessoren.
Das Letzte Problem, relativ zu Atomarität ist, dass sich die spezifisch für read-modify-write-Atomarität. Das heißt, wie gewährleisten Sie, dass, wenn ein Wert gelesen wird, aktualisiert sich in den Wert und die geschrieben, dass dies geschieht atomar, auch über Prozessoren, wenn mehr als eine. So, für diese zu arbeiten, ohne bestimmte Synchronisierung an, die Objekte würden erfordern, dass alle möglichen threads den Zugriff auf die variable sind die Leser NUR, sondern erwarten, dass nur ein thread je sein kann einen Schriftsteller zu einer Zeit. Wenn dies nicht der Fall ist, dann müssen Sie ein sync-Objekt zur Verfügung, um gewährleisten zu können, werden Atomare Aktionen auf read-modify-write-Aktionen auf die variable.
InformationsquelleAutor der Antwort Tall Jeff
Ihre Lösung werden 100% der CPU, unter anderen Problemen. Google als "condition variable".
InformationsquelleAutor der Antwort
Chris Jester-Jung wies darauf hin, dass:
so, die einzige wahre Antwort ist die Implementierung eines Synchronisierungs-system, richtig?
InformationsquelleAutor der Antwort fabiopedrosa
Verwenden Sie die flüchtigen Schlüsselwort Hinweis an den compiler, dass der Wert jederzeit ändern kann.
InformationsquelleAutor der Antwort Adam Pierce
Nein, es ist nicht sicher. Wenn Sie deklarieren die variable volatile ist, dann ist der complier soll, um code zu generieren, die immer zu Lasten der Variablen aus dem Speicher gelesen.
InformationsquelleAutor der Antwort Lou Franco
Wenn der Umfang stimmt ( "extern", global, etc. ), dann wird die Veränderung bemerkt. Die Frage ist Wann? Und in welcher Reihenfolge?
Das problem ist, dass der compiler kann und Häufig wird neu -, um Ihre Logik zu füllen, ist es konkurrierende pipelines, wie eine performance-Optimierung.
Es nicht wirklich zeigen, der in Ihre spezifischen Beispiel, weil es nicht alle anderen Anweisungen, um Ihre Aufgabe, aber Stell dir mal die Funktionen erklärt, nachdem Ihre bool zuweisen, ausführen vor die Abtretung mitteilt.
Check-out Pipeline-Hazard bei wikipedia oder Suche bei google nach "compiler-Anweisung Neuordnung"
InformationsquelleAutor der Antwort kervin
Wie andere gesagt haben, die
volatile
Schlüsselwort ist dein Freund. 🙂Werden Sie wahrscheinlich feststellen, dass dein code funktionieren würde, wenn Sie hatte alle von der Optimierung Optionen deaktiviert im gcc. In diesem Fall (glaube ich) es behandelt alles als flüchtig und als ein Ergebnis die variable zugegriffen wird, im Speicher für jeden Betrieb.
Mit jeder Art von Optimierung eingeschaltet, wird der compiler versuchen, verwenden Sie eine lokale Kopie in einem register. Je nach Funktionen, kann dies bedeuten, dass Sie nur die Veränderung in der variable zeitweise oder, im schlimmsten Fall, nie.
Mithilfe des keyword -
volatile
zeigt dem compiler, dass der Inhalt dieser variable kann sich jederzeit ändern und es sollte nicht Verwendung eines lokal zwischengespeicherte Kopie.All das sagte, Sie können finden bessere Ergebnisse (wie angedeutet durch Jeff) durch die Verwendung eines semaphor-variable oder Bedingung.
Diese ist eine angemessene Einführung in das Thema.
InformationsquelleAutor der Antwort Andrew Edgecombe