Schauen wir uns diesen Code an:
Java.util.bitset; Thread t1 = neuer Thread (neuer Runnable () {public void run () {try {latch.await (); Thread.sleep (1000);} catch (exception ex) {} bsSet (1);}); Thread t2 = neuer Thread (neuer Runnable () {public void run () {try {latch.await (); Thread.sleep (1000);} catch (Ausnahme E) {} Bs.set (2);}}) ; :}}Die Frage ist, was ist das Ergebnis dieser Codeausgabe? Welche Ergebnisse können es sogar auf dem zusammengebrochenen JVM ausgeben? Welche Ergebnisse dürfen die Ausgabe immer noch drucken?
Schauen wir uns an, was dieses Programm tut:
Als nächstes müssen wir einige Testfälle erstellen, um diese Verhaltensweisen zu überprüfen. Offensichtlich kann einer von ihnen dieses Beispiel nur ausführen und dann die Ergebnisse beobachten und die obigen Fragen beantworten.
Sorgfalt kann einen Zufall machen
Glücklicherweise können wir Werkzeuge verwenden. JCStress ist ein Testwerkzeug zur Lösung solcher Probleme.
Wir können unseren Testfall leicht als eine Form schreiben, die JCStress erkennen kann. Tatsächlich hat es für uns eine Vielzahl von Schnittstellen vorbereitet. Wir brauchen ein Beispiel.
Wir verwenden einen Actor2_Arbiter1_Teest <BitSet, booleanResult2> Schnittstelle. Wir müssen einen Java 8 JVM finden, um es auszuführen, aber jetzt ist dies kein Problem.
Schauen Sie sich die Implementierung unten an.
Öffentliche Klasse Anexampletest Implements Actor2_Arbiter1_test <bitset, booleanResult2> {@Override public void actor1 (Bitset S., booleanResult2 r) {sset (1);} @Override Public Void Actor2 (Bitset S, Booleanresult2 {S. );} @Override public void Arbiter1 (Bitset S., BooleanResult2 R) {R.R1 = S.Get (1); ;} @Override public boolenrsult2 newresult () {return New BooleanResult2 ();}}
Wenn Sie diesen Test nun ausführen, wird die Steuerung alle möglichen Tricks ausprobieren, um alle möglichen Kombinationen von Faktoren zu erhalten, die diese Aktionen vorantreiben: parallel oder nicht merger, es gibt keine Lasterkennung, und viele Male gibt es viele Male in einer Zeile, viele Male. Oft, oft, oft werden alle möglichen Ergebnisse aufgezeichnet.
Wenn Sie wissen möchten, wie Ihr paralleler Code eingeschaltet ist, ist dies eine bessere Möglichkeit, einen hohlen Gedanken zu graben und an alle Details zu denken als Sie selbst.
Um die umfassende Bequemlichkeit der JCStress -Einschränkungen zu verwenden, müssen wir sie mit einer Erläuterung möglicher Ergebnisse geben.
<test name = "org.openjdk.jcstress.tests.custom.anexampletest"> <beitragen by> Oleg Shelajev < > Match> [TRUE, TRUE] </match> <erwarten> Akzeptable </erwartete> <beschreibung> Sehen Sie alle Updates intakt. /Erwartung> <BEKRÜFUNGS> T2 T1 -Ergebnis > </Case> <nmatched> <erwarten> verboten </exten> <beschreibung> Alle anderen Fälle sind unter unlenexpected.
Jetzt sind wir bereit, dass dieses Biest durch die Verwendung der folgenden Befehlszeile zum Ausführen von Tests anfängt.
Java -xx:+entrlockdiagnosticvMoptions -xx:+whiteboxapi -xx: -ResterictContended -Jar -Tests -custot/target/jcstress.jar -t = ".*AnexampleTest"
Das Ergebnis, das wir erhalten, ist ein eleganter Bericht.
Es ist klar, dass wir nicht nur die erwarteten Ergebnisse erzielen können, dh, dass beide Threads ihre Positionen festgelegt haben, sondern auch auf einen Wettbewerbszustand stößt und ein Thread das Ergebnis eines anderen Threads abdeckt.
Selbst wenn Sie so etwas sehen, müssen Sie die ruhige Mentalität von "Die Bergleute haben ihre eigenen Tricks", nicht wahr?
Wenn Sie jedoch darüber nachdenken, wie Sie diesen Code ändern sollen, müssen Sie die Bitset -Klasse in Javadoc sorgfältig lesen und feststellen, dass es sich nicht um eine Thread -Sicherheit handelt und eine externe Synchronisation erfordert. Dies kann leicht erreicht werden, indem die Einstellungswerte von synchronen Blöcken erhöht werden.
synchronisiert (bs) {bs.set (1);}