Frage

Ich habe zwei Threads, einen, der ein Int aktualisiert, und einen, der es liest.Dies ist ein statistischer Wert, bei dem die Reihenfolge der Lese- und Schreibvorgänge keine Rolle spielt.

Meine Frage ist: Muss ich den Zugriff auf diesen Multibyte-Wert überhaupt synchronisieren?Oder, anders ausgedrückt, kann ein Teil des Schreibvorgangs abgeschlossen sein und unterbrochen werden, und dann erfolgt der Lesevorgang.

Stellen Sie sich beispielsweise einen Wert = 0x0000FFFF vor, der den inkrementierten Wert 0x00010000 erhält.

Gibt es eine Zeit, in der der Wert wie 0x0001FFFF aussieht und über die ich mir Sorgen machen sollte?Je größer der Typ, desto wahrscheinlicher ist es sicherlich, dass so etwas passiert.

Ich habe diese Art von Zugriffen immer synchronisiert, war aber neugierig, was die Community denkt.

War es hilfreich?

Lösung

Zunächst könnte man meinen, dass liest und schreibt der nativen Maschinengröße sind atomar, aber es gibt eine Reihe von Problemen mit einschließlich Cache-Kohärenz zwischen den Prozessoren / Kerne beschäftigen. Verwenden Sie atomare Operationen wie Verschlungene * auf Windows und das Äquivalent auf Linux. C ++ 0x wird eine „atomare“ Vorlage müssen diese in einer schönen und plattformübergreifende Schnittstelle zu wickeln. Denn jetzt, wenn Sie eine Plattform Abstraktionsschicht verwenden kann es diese Funktionen zur Verfügung stellen. ACE wird, finden Sie in der Klassenvorlage ACE_Atomic_Op .

Andere Tipps

Boy, was für eine Frage. Die Antwort auf die lautet:

  

Ja, nein, hmmm, na ja, es hängt

Es kommt alles auf die Architektur des Systems. Auf einer IA32 eine korrekt ausgerichtete Adresse wird eine atomare Operation sein. Unaligned schreibt möglicherweise atomar sein, es hängt von dem Caching-System im Einsatz. Wenn der Speicher in einer einzigen L1-Cache-Linie liegt, dann ist es atomar, sonst ist es nicht. Die Breite des Busses zwischen den CPU und RAM kann die atomare Natur beeinflussen: a korrekt ausgerichteten 16-Bit-Schreibvorgang auf einer 8086 atomic war, während die gleiche Schreib auf einer 8088 nicht war, weil die 8088 nur einen 8-Bit-Bus hatte, während die 8086 A hatte 16-Bit-Bus.

Auch wenn Sie mit C / C ++ vergessen Sie nicht, den gemeinsamen Wert als flüchtig zu markieren, da sonst die Optimierers wird denken, die Variable nie in einem Ihrer Threads aktualisiert wird.

Wenn Sie Lesen / Schreiben von 4-Byte-Wert und es ist DWORD bündig im Speicher und Sie auf der I32-Architektur laufen, liest und schreibt atomar sind.

Ja, Sie müssen Zugriffe synchronisieren. In C ++ 0x wird es ein Datum Rasse und nicht definiertes Verhalten sein. Mit POSIX-Threads ist es schon nicht definiertes Verhalten.

In der Praxis könnte man schlechte Werte, wenn der Datentyp größer als die native Wortgröße. Auch könnte ein anderer Thread nie sehen den Wert geschrieben aufgrund Optimierungen Bewegen des Lese- und / oder schreiben.

Sie müssen synchronisiert werden, aber auf bestimmte Architekturen gibt es effiziente Möglichkeiten, es zu tun.

Am besten ist Subroutinen zu verwenden (vielleicht hinter Makros maskiert), so dass Sie bedingt Implementierungen mit plattformspezifischen ersetzen können.

Der Linux-Kernel hat bereits einige dieser Code.

Unter Windows Verriegelt *** Austausch *** hinzufügen garantiert atomar sein.

Um zu wiederholen, was alle sagten oben, die Sprache vorge C ++ 0x nichts über Shared-Memory-Zugriff von mehreren Threads garantieren kann. Jegliche Garantien wären bis zu den Compiler.

Definitiv NEIN! Diese Antwort von unserer höchsten C ++ Behörde, M. Boost:
Operationen auf "normale" Variablen sind nicht atomar sein garantiert.

Nein, sie sind nicht (oder zumindest kann man nicht davon ausgehen, sie sind). Having said that, gibt es einige Tricks sind diese atomar zu tun, aber sie sind in der Regel nicht tragbar (siehe

Ich stimme mit vielen und vor allem Jason . Am Fenster, würde man wahrscheinlich InterlockedAdd und seine Freunde verwenden.

Asside aus dem Cache-Problem oben erwähnt ...

Wenn Sie Port den Code an einen Prozessor mit einer kleineren Registergröße wird es nicht mehr atomar sein.

IMO, Threadingprobleme sind zu dornige, es zu riskieren.

Hier können Sie dieses Beispiel nehmen

int x;
x++;
x=x+5;

Die erste Anweisung wird angenommen, atomar zu sein, weil es zu einer einzigen INC Montagerichtlinie übersetzt, die einen einzigen CPU-Zyklus dauert. Allerdings erfordert die zweite Zuordnung mehrere Operationen so ist es eindeutig nicht eine atomare Operation.

Ein weiterer z.B.

x=5;

Auch hier müssen Sie den Code zerlegen, um zu sehen, was genau hier passiert.

tc, Ich denke, der Moment, den Sie verwenden, um eine Konstante (wie 6), würde der Befehl nicht in einem Maschinenzyklus abgeschlossen sein. Versuchen Sie, den Befehlssatz von x + = 6 im Vergleich zu x sehen ++

Einige Leute denken, dass ++ c ist atomar, sondern haben ein Auge auf der Montag erzeugt. Zum Beispiel mit 'gcc ES':

movl    cpt.1586(%rip), %eax
addl    $1, %eax
movl    %eax, cpt.1586(%rip)

einen int zu erhöhen, der Compiler zunächst in ein Register geladen werden, und speichert sie wieder in den Speicher. Dies ist nicht atomar.

Die einzige tragbare Art und Weise ist es, den sig_atomic_t Typen für Ihren Compiler in signal.h Header definiert zu verwenden. In den meisten C und C ++ Implementierungen, das ist ein int. Dann erklären Sie Ihre Variable als "volatile sig_atomic_t."

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top