Es gibt keine Threads in Standard C++ und Threads cannot be implemented as a library.
Daher hat der Standard nichts über das Verhalten von Programmen zu sagen, die Threads verwenden. Sie müssen prüfen, welche zusätzlichen Garantien Ihre Threading-Implementierung bietet.
das gesagt ist, in Threading-Implementierungen habe ich verwendet:
(1) ja, Sie, dass irrelevante Werte annehmen können, nicht auf Variablen geschrieben. Andernfalls wird das gesamte Speichermodell aus dem Fenster gelöscht. Aber sei vorsichtig, wenn du sagst "ein anderer Thread" setzt niemals b
auf falsch, das heißt überall, immer. Wenn dies der Fall ist, könnte dieser Schreibvorgang möglicherweise neu angeordnet werden, um während der Schleife ausgeführt zu werden.
(2) Nein, der Compiler kann die Zuordnungen zu b1 und b2 neu anordnen, daher ist es möglich, dass b1 am Ende wahr und b2 falsch ist. In solch einem einfachen Fall weiß ich nicht, warum es neu ordnen würde, aber in komplizierteren Fällen könnte es sehr gute Gründe geben.
[Edit: oops, als ich zur Antwort kam (2) hatte ich vergessen, dass b volatil war. Lesen von einer volatilen Variablen wird nicht neu geordnet, sorry, also ja bei einer typischen Threading-Implementierung (wenn es so etwas gibt), können Sie davon ausgehen, dass Sie nicht mit b1 wahr und b2 falsch enden werden.]
(3) wie 1.volatile
hat überhaupt nichts mit Threading zu tun. Es ist jedoch in einigen Implementierungen (Windows) ziemlich aufregend und könnte tatsächlich Speicherbarrieren beinhalten.
(4) auf einer Architektur, wo int
schreibt atomare ja, obwohl volatile
hat nichts damit zu tun. Siehe auch ...
(5) Überprüfen Sie die Dokumente sorgfältig. Wahrscheinlich ja, und wieder flüchtig ist irrelevant, weil auf fast allen Architekturen int
schreibt atomare sind. Aber wenn int
schreiben ist nicht atomar, dann nein (und nein für die vorherige Frage), auch wenn es flüchtig ist, könnte man im Prinzip einen anderen Wert bekommen. Angesichts dieser Werte 7 und 8 sprechen wir jedoch über eine ziemlich seltsame Architektur für das Byte, das die relevanten Bits enthält, die in zwei Stufen geschrieben werden, aber mit anderen Werten könnte man plausibler einen partiellen Schreibvorgang bekommen.
Für ein plausibleres Beispiel nehmen Sie an, dass Sie aus irgendeinem seltsamen Grund ein 16-Bit-Int auf einer Plattform haben, wo nur 8-Bit-Schreiboperationen atomar sind. Odd, aber legal, und seit int
müssen mindestens 16 Bits sein, die Sie sehen können, wie es zustande kommen könnte. Nehmen wir weiter an, dass Ihr Anfangswert ist 255. Dann rechtlich umgesetzt werden erhöhen könnte als:
- den alten Wert
- Schritt in einem Register
- das signifikanteste Byte des Ergebnisses
- schreiben schreiben lesen die niedrigstwertiges Byte des Ergebnisses.
Ein Nur-Lese-Threads, die Inkrementierung Faden zwischen den dritten und vierten Schritten, dass unterbrochen, 511. den Wert sehen könnte, wenn die Schreibvorgänge in der anderen Reihenfolge sind, könnte es 0.
Ein sehen Inkonsistente Werte können permanent zurückbleiben, wenn ein Thread 255 schreibt, ein anderer Thread gleichzeitig 256 schreibt und die Schreibvorgänge verschachtelt werden. Unmöglich auf vielen Architekturen, aber um zu wissen, dass dies nicht passieren wird, müssen Sie zumindest etwas über die Architektur wissen. Nichts im C++ - Standard verbietet dies, weil der C++ - Standard davon spricht, dass die Ausführung durch ein Signal unterbrochen wird, ansonsten aber kein Konzept der Ausführung durch einen anderen Teil des Programms unterbrochen wird und kein Konzept der gleichzeitigen Ausführung. Deshalb sind Threads nicht nur eine andere Bibliothek - das Hinzufügen von Threads ändert das C++ - Ausführungsmodell grundlegend. Es erfordert die Implementierung, Dinge anders zu machen, wie Sie schließlich herausfinden werden, wenn Sie zum Beispiel Threads unter gcc verwenden und vergessen, -pthreads
anzugeben.
Das gleiche auf einer Plattform, wo ausgerichtetint
schreibt atomar sind, aber nicht ausgerichteten int
schreibt sind zulässig und nicht atomar passieren könnte. Zum Beispiel IIRC auf x86, unausgerichtete int
Schreibvorgänge sind nicht atomar garantiert, wenn sie eine Cache-Zeilengrenze überschreiten. x86-Compiler werden eine deklarierte int
Variable aus diesem Grund und anderen nicht falsch ausrichten. Aber wenn Sie Spiele mit Strukturpackung spielen, könnten Sie wahrscheinlich ein Beispiel provozieren.
Also: so ziemlich jede Implementierung gibt Ihnen die Garantien, die Sie brauchen, aber könnte es auf eine ziemlich komplizierte Art und Weise tun.
Im Allgemeinen habe ich festgestellt, dass es nicht wert ist, sich auf plattformspezifische Garantien über Speicherzugriff zu verlassen, die ich nicht vollständig verstehe, um Mutexe zu vermeiden. Verwenden Sie einen Mutex, und wenn das zu langsam ist, verwenden Sie eine qualitativ hochwertige, lockfreie Struktur (oder implementieren Sie einen Entwurf für einen), die von jemandem geschrieben wurde, der die Architektur und den Compiler wirklich kennt.Es wird wahrscheinlich richtig sein, und vorbehaltlich der Korrektheit wird wahrscheinlich alles übertreffen, was ich selbst erfinde.
Wo Sie haben gelesen, dass "nichts in C-Atom ist ++"? Ich hatte den Eindruck, dass alle Lese- oder Schreibvorgänge eines einzelnen Bytes atomar waren. Sie könnten also den Wert eines Bool überprüfen oder ein Char zuweisen ... oder vielleicht waren es 32 Bits, die garantiert atomar waren? Wäre das dann 64 in einer 64-Bit-Architektur? – mpen
@Mark: Ich denke, er meinte, dass die C++ - Sprache nicht die Atomarität von irgendetwas garantiert. Es hängt von der spezifischen Implementierung (und der CPU-Architektur) ab, was atomar ist oder nicht. – jalf
@jalf: Nun ... okay, dann ist es vielleicht keine Eigenschaft von C++, aber es ist immer noch eine einigermaßen sichere Annahme. So können wir zumindest die Frage (1) mit Sicherheit beantworten. – mpen