Beispiel für ein korrekt synchronisiertes Programm mit Datenrennen im Java-Speichermodell

8

In JLS, § 17.4. 5. Geschieht-vor der Bestellung , es sagt das

  

Ein Programm wird genau dann synchronisiert, wenn alle sequentiell konsistenten Ausführungen frei von Datenrennen sind.

Laut Diskussion in < em> Lässt ein richtig synchronisiertes Programm noch Datenrennen zu (Teil I) , erhalten wir folgende Schlussfolgerung:

  

Ein Programm kann korrekt synchronisiert werden und Datenrennen haben.

Die Kombination von zwei Schlussfolgerungen bedeutet, dass es ein solches Beispiel geben muss:

  

Alle sequentiell konsistenten Ausführungen eines Programms sind datenlauffrei, aber die normalen Ausführungen (Ausführungen, die nicht sequentiell konsistente Ausführungen sind) eines solchen Programms enthalten Datenrennen.

Nach langem Überlegen kann ich immer noch kein solches Codebeispiel finden. Also was ist mit dir?

    
newman 19.08.2012, 03:47
quelle

1 Antwort

6

Es ist nicht wahr, dass "ein Programm korrekt synchronisiert werden kann und Datenrennen haben". Das Beispiel von assylias in dieser Diskussion ist nicht korrekt synchronisiert . Es ist korrekt vom übergeordneten funktionalen Standpunkt aus - das Datenrennen, das es enthält, zeigt sich nicht als Fehler. Es ist ein sogenanntes "gutartiges" Datenrennen, aber das ist irrelevant, wenn man die JLS-Definitionen diskutiert.

Ein Programm, dessen sequentiell konsistente Ausführung keine Datenrennen enthält, garantiert garantiert keine Datenrennen in irgendeiner Ausführung, sequentiell konsistent oder nicht. Wie die JLS sagt,

  

Dies ist eine extrem starke Garantie für Programmierer. Programmierer müssen nicht über Neuanordnungen nachdenken, um festzustellen, dass ihr Code Datenrennen enthält. Daher müssen sie bei der Bestimmung, ob ihr Code korrekt synchronisiert ist, nicht über Neuordnungen nachdenken. Sobald die Feststellung getroffen ist, dass der Code korrekt synchronisiert ist, muss sich der Programmierer nicht sorgen, dass Umordnungen seinen Code beeinflussen.

Bitte beachten Sie, dass die Definition eines korrekt synchronisierten Programms nur auf sequentiell konsistente Ausführungen beschränkt ist [em] als eine Höflichkeit gegenüber dem Programmierer , was ihm die starke Garantie gibt, dass sequentiell konsistente Ausführungen die einzigen sind oder sie muss darüber nachdenken und alle anderen Ausführungen haben automatisch die gleiche Garantie.

AKTUALISIEREN

Es ist leicht, sich in der Terminologie des JMM zu verlieren und subtile Fehlinterpretationen führen später zu tiefen Missverständnissen. Nimm dir deshalb diese zu Herzen:

  • Eine Ausführung ist einfach eine Gruppe von Inter-Thread-Aktionen. Es gibt keine a priori Anweisung dazu. Insbesondere gibt es keine zeitliche Reihenfolge .

Dies ist eine kontraintuitive Definition, daher müssen wir vorsichtig sein: Jedes Mal, wenn wir Ausführung sagen, müssen wir uns eine Menge an Aktionen vorstellen , niemals a Reihe von ihnen. Wann immer wir eine partielle Ordnung definieren, sollten wir uns vorstellen, dass mehrere Taschen aneinandergereiht sind.

  • Ein Programm enthält Anweisungen zum Ausführen von Aktionen. Jeder derartige Befehl kann null oder mehrere Male ausgeführt werden, wobei null oder mehr verschiedene Aktionen zu der bestimmten Ausführung beitragen;
  • Eine Ausführung kann oder darf nicht eine Ausführungsreihenfolge haben, was eine Gesamtbestellung über alle Aktionen ist ;
  • Eine sequentielle konsistente Ausführung ist die, die Sie erhalten würden, wenn all Ihre gemeinsamen Variablen flüchtig wären. Diese Art der Ausführung hat immer eine bestimmte Ausführungsreihenfolge;
  • eine sequentielle inkonsistente Ausführung ist Ihre reale Ausführung eines Programms: nicht-volatile Variablen sind beteiligt und der Compiler reordert liest und schreibt, es gibt Caches, Thread -Lokale Geschäfte, usw.
  • Die Synchronisierungsreihenfolge ist die gesamte Reihenfolge aller Synchronisationsaktionen , die von einer Ausführung ausgeführt werden. In Bezug auf die Ausführung selbst ist es immer noch eine Teilaufordnung, da nicht alle Aktionen Synchronisationsaktionen sind; vor allem Lese- und Schreibvorgänge von nicht-flüchtigen Variablen. Jede Ausführung, sei sie sequentiell konsistent oder nicht, hat eine bestimmte Synchronisationsreihenfolge;
  • Ebenso wird die hases-before Reihenfolge für eine bestimmte Ausführung eines Programms definiert und als transitive Schließung der Synchronisationsreihenfolge mit der Programmreihenfolge abgeleitet.

Es ist interessant festzustellen, dass die Synchronisationsreihenfolge zu einer Gesamtbestellung würde, wenn all Ihre geteilten vars flüchtig wären und als solche die Definition der Ausführungsreihenfolge . Auf diese Weise kommen wir aus einem anderen Blickwinkel zu der Schlussfolgerung, dass alle Ausführungen eines solchen Programms sequentiell konsistent wären.

Ich habe tief gegraben, um den JLS-Fehler in der Definition eines Datenrennens zu verstehen:

"Wenn ein Programm zwei in Konflikt stehende Zugriffe (§ 17.4.1) enthält, die nicht durch eine happes-before Beziehung angeordnet sind, wird gesagt, dass es ein Datenrennen enthält."

Zunächst ist es nicht das Programm , das Datenrennen enthält, sondern eine Programmausführung . Wenn wir uns wieder auf das Originalpapier beziehen, das das Java-Speichermodell definiert, sehen wir, dass dies korrigiert wird:

"Zwei Zugriffe x und y bilden bei der Ausführung eines Programms eine Datenrasse, wenn sie aus verschiedenen Threads stammen, sie konfligieren und nicht nach passiert-vor . "

Dies führt jedoch immer noch dazu, dass volatile Variablen als Datenrennen definiert werden. Betrachten Sie das folgende Diagramm hases-before :

%Vor%

r1 Beobachter der Schreib w1 .Es wurde von einem anderen zu lesen, r0 , und die Schreib voraus durch eine andere gefolgt, w2 . Beachten Sie jetzt gibt es keinen Weg zwischen r0 und entweder w1 oder w2 ; ebenfalls zwischen r1 und w2 . All dies sind Beispiele eines Daten Rennen durch die Definition.

noch tiefer Graben, aber ich habe festgestellt, diesen Beitrag auf der memoryModel Mailingliste . Es sagt "eine Daten Rennen sollte als widersprüchliche Aktionen auf nicht-flüchtigen Variablen definiert werden die nicht von hours-before angeordnet werden. "Nur mit dieser Hinzufügung würde die Lücke geschlossen, aber diese hat noch nicht die offizielle JLS-Version betreten.

    
Marko Topolnik 19.08.2012, 06:32
quelle

Tags und Links