Wie können Race Conditions um nicht korrekt veröffentlichte Werte herum demonstriert werden?

9

Ich lese "Java Concurrency in der Praxis" und schaue mir den Beispielcode auf Seite 51 an.

Nach dem Buch besteht die Gefahr, dass dieser Codeabschnitt fehlerhaft wird, wenn er nicht ordnungsgemäß veröffentlicht wurde. Weil ich gerne Beispiele modelliere und sie aufbringe, um zu beweisen, wie sie funktionieren. Ich habe versucht, es einen AssertionError werfen zu lassen, aber gescheitert. (Führt mich zu meiner vorherigen Frage )

Kann jemand Beispielcode posten, so dass ein AssertionError ausgelöst wird? Regel: Ändern Sie nicht die Holder-Klasse.

%Vor%

Ich habe die Klasse modifiziert, um sie fragiler zu machen, aber ich kann immer noch keinen AssertionError bekommen.

%Vor%

Ist es möglich, dass eine der obigen Klassen einen AssertionError wirft? Oder müssen wir akzeptieren, dass sie dies gelegentlich tun und wir können keinen Code schreiben, um es zu beweisen?

    
andy boot 12.04.2010, 19:06
quelle

5 Antworten

3

Ich würde dies auf einem Multiprozessor-Rechner für ein paar Stunden ausführen und sehen, was passiert (entfernen Sie den Schlaf, wenn Sie Ihren Holder2 benutzen). Solche Race Conditions sind vielleicht selten oder nicht vorhanden auf Ihrer speziellen Maschine - aber zumindest versuchen Sie diese auf eine Million Fälle zu provozieren, indem Sie Millionen von Malen versuchen.

%Vor%     
leeeroy 12.04.2010, 19:27
quelle
1

Wie Bobby Shaftoe im anderen Thread gesagt hat, können Sie sich nicht darauf verlassen, dass der Code nur so oft ausgeführt wird, um zu zeigen, dass der Fehler passieren kann oder nicht. Wenn Sie von einer Assembly-Ebene aus darüber nachdenken, wird es für n! = N sehr schwierig sein, da es so wenige Aufrufe gibt und darauf vertraut ist, dass der Prozess zu einem sehr genauen Zeitpunkt abgeschaltet wird.

Wenn Sie in der Lage sein möchten, zu zeigen, ob ein konkurrierendes System nachweisbar gültig ist, wäre es besser, es mit etwas wie beschrifteten Übergangssystemen zu modellieren. Probieren Sie das LTSA-Tool aus, wenn Sie Parallelität nachweisen oder Fehler finden möchten.

Ссылка

    
Oli 12.04.2010 19:40
quelle
1

Im Beispiel ist das Buch, das die Klasse Holder gibt, nicht direkt die Ursache des Problems, sondern es besagt:

Das Problem hier ist nicht die Holder-Klasse selbst, sondern dass der Holder nicht richtig veröffentlicht wird. Holder kann jedoch gegen unkorrekte Veröffentlichung immun gemacht werden, indem das n-Feld für endgültig erklärt wird, was Holder unveränderlich machen würde; siehe Abschnitt 3.5.2.

Zuvor erwähnt es den folgenden Code, der das Thema des Problems ist:

%Vor%

Um es neu zu erstellen, müssen Sie also eine Publisher-Klasse und zwei Threads erstellen, einen, der initialize aufruft, und einen, der assert aufruft.

Nachdem ich das gesagt habe, habe ich versucht, es selbst neu zu erstellen und habe es immer noch nicht geschafft :(

Unten ist mein erster Versuch, aber es gibt eine bessere Erklärung des Problems bei Ссылка

%Vor%     
Steve McDowell 11.03.2011 11:57
quelle
0

Ich glaube nicht, dass der Assertionsfehler auftreten kann, ohne die Klasse Holder zu ändern. Ich denke, das Buch ist falsch.

Der Assertionsfehler wird nur verursacht, wenn assertSanity () für ein partially constructed object aufgerufen wird. Wie kann ein Thread, der nicht der Konstruktenthread ist, auf ein teilweise konstruiertes Objekt verweisen? AFAIK, ist nur in den folgenden zwei Fällen möglich:

  1. Veröffentlichen Sie this im Konstruktor. Z.B. Weisen Sie this einer gemeinsamen Variablen zu. Dies kann in unserem Beispielcode nicht passieren, da der Konstruktor von Holder das nicht tut.
  2. Die nicht statische innere Klasse einer Klasse kann sich auf ihr übergeordnetes Element beziehen, selbst wenn ihr Elternteil teilweise konstruiert ist. Dies kann auch nicht passieren, weil Holder keine innere Klasse hat.

Beachten Sie, dass der folgende Code in dem Buch kein teilweise konstruiertes Objekt veröffentlicht:

%Vor%

Wenn Sie initialize() disassemblieren, erhalten Sie Folgendes:

%Vor%

Beachten Sie, dass putfield holder nach invokespecial <init> ausgeführt wird. Dies bedeutet, dass die Zuweisung von holder nach Abschluss des Konstruktors erfolgt. Das teilweise konstruierte Objekt wird nur im Stack des Threads gespeichert. Es ist nicht veröffentlicht.

Wenn Sie den Assertionsfehler auf vernünftige Art und Weise auslösen können (z. B. ist die Reflexion nicht sinnvoll), setzen Sie sie hier. Ich stimme Ihnen zu.

    
Wu Yongzheng 30.09.2013 07:12
quelle
-1

Sie können den Wert von n zu keinem Zeitpunkt ändern, indem Sie Folgendes verwenden:

%Vor%     
Igor Artamonov 12.04.2010 19:23
quelle

Tags und Links