InterlockedExchange und Speicher-Sichtbarkeit

8

Ich habe den Artikel Synchronization and Multiprocessor Issues gelesen und ich habe eine Frage zu InterlockedCompareExchange und InterlockedExchange. Die Frage bezieht sich eigentlich auf das letzte Beispiel in dem Artikel. Sie haben zwei Variablen iValue und fValueHasBeenComputed und in CacheComputedValue() modifizieren sie jede mit InterlockedExchange :

%Vor%

Ich verstehe, dass ich InterlockedExchange für die Änderung von iValue verwenden kann, aber es genügt,

zu tun %Vor%

Ist es also notwendig, InterlockedExchange zu verwenden, um iValue zu setzen? Oder andere Threads sehen iValue korrekt, auch wenn iValue = ComputeValue(); . Ich meine, die anderen Threads sehen iValue korrekt, weil InterlockedExchange dahinter steht.

Es gibt auch das Papier Ein prinzipienbasiertes sequenzielles Speichermodell für Microsoft Native Code-Plattformen . Es gibt das 3.1.1 Beispiel mit mehr oder weniger dem gleichen Code. Eine der Empfehlungen Make y interlocked . Hinweis - nicht sowohl y als auch x .

Aktualisieren
Nur um die Frage zu klären. Das Problem ist, dass ich einen Widerspruch sehe. Das Beispiel aus "Synchronization and Multiprocessor Issues" verwendet zwei InterlockedExchange . Im Gegensatz dazu gibt Herb Sutter in dem Beispiel 3.1.1 "Basic Reodering" (das meiner Meinung nach dem ersten Beispiel sehr ähnlich ist) diese Empfehlung.

  

"Verschränkt machen: Wenn y verriegelt ist, gibt es keine Wettfahrt auf y   weil es atomar aktualisierbar ist und es keine Rasse auf x gibt, weil a   - & gt; b - & gt; d. "

. In diesem Entwurf verwende Herb nicht zwei verschränkte Variablen (Wenn ich recht habe, meint er InterlockedExchange nur für y ).

    
Sergei Kurenkov 07.10.2011, 09:41
quelle

4 Antworten

1

Sie haben das getan, um partielles Lesen / Schreiben zu verhindern, wenn die Adresse von iValue nicht auf eine Adresse ausgerichtet ist, die atomaren Zugriff garantiert. Dieses Problem tritt auf, wenn zwei oder mehr physische Threads versuchen, den Wert gleichzeitig zu schreiben, oder wenn einer liest und einer versucht, gleichzeitig zu schreiben.

Als sekundärer Punkt ist anzumerken, dass Speicher nicht immer global sichtbar sind. Sie werden nur dann sichtbar sein, wenn sie serialisiert werden, entweder durch einen Zaun oder durch eine Bussperre.

    
Necrolis 07.10.2011 11:10
quelle
0

Sie erhalten einfach eine atomare Operation mit InterlockedExchange . Warum brauchst Du es? Ursache InterlockedExchange macht 2 Dinge.

  1. Ersetzt einen Wert der Variablen
  2. Gibt einen alten Wert zurück

Wenn Sie in 2 Operationen die gleichen Dinge machen (also zuerst den Wert prüfen und dann ersetzen), können Sie sich schinden lassen, wenn zwischen diesen 2 andere Anweisungen (in einem anderen Thread) auftreten.

Und Sie verhindern auch Datenrennen über diesen Wert. hier erhalten Sie eine gute Erklärung warum lesen / schreiben auf einem LANG ist nicht atomar

    
Oleg 07.10.2011 11:10
quelle
0

Es gibt zwei plausible Lösungen für den Widerspruch, den Sie beobachtet haben.

Erstens ist das zweite Dokument in dieser Hinsicht einfach falsch. Es ist schließlich ein Entwurf. Ich bemerke, dass das Beispiel, auf das Sie sich beziehen, ausdrücklich besagt, dass der Programmierer sich nicht darauf verlassen kann, dass die Schreiboperationen atomar sind, was bedeutet, dass beide Schreiboperationen tatsächlich miteinander verknüpft sein müssen.

Das andere ist, dass die zusätzliche Verriegelung in diesem speziellen Beispiel möglicherweise nicht erforderlich ist, weil es ein ganz besonderer Fall ist: nur ein einzelnes Bit der Variablen wird geändert. Allerdings scheint die Spezifikation, die entwickelt wird, dies nicht als Prämisse zu erwähnen, also bezweifle ich, dass dies beabsichtigt ist.

    
Harry Johnston 08.10.2011 22:44
quelle
0

Ich denke, diese Diskussion hat die Antwort auf die Frage: Implizite Speicherbarrieren .

  

Frage : ruft InterlockedExchange (impliziter Vollzaun) in T1 auf   und T2, Gurenness, dass T2 den von T1 vor dem Schreiben durchgeführten Schreibvorgang "sieht"   Zaun? (A-, B- und C-Variablen), obwohl diese Variablen nicht sind   auf der gleichen Cache-Line wie Foo und Bar?

     

Antwort : Ja - der vollständige Zaun, der von InterlockedExchange generiert wird   garantieren, dass die Schreibvorgänge nach A, B und C nicht über die Zeit nachbestellt werden   Implizierter InterlockedExchange-Aufruf. Das ist der Punkt von   Speicherbarrierensemantik. Sie müssen nicht im selben Cache sein   Linie.

Speicherbarrieren: eine Hardware-Ansicht für Software-Hacker und < a href="http://msdn.microsoft.com/en-us/library/ee418650%28VS.85%29.aspx"> Sperrenlose Programmierung Überlegungen für Xbox 360 und Microsoft Windows sind auch sehr interessant. p>     

Sergei Kurenkov 19.10.2011 10:24
quelle