Beim Durchsuchen des Codes für die Java 8-Version von ForkJoinPool (die einige interessante Änderungen gegenüber Java 7 enthält) bin ich auf dieses Konstrukt gestoßen ( hier ):
do {} while (!blocker.isReleasable() &&
!blocker.block());
Ich habe Probleme damit, warum Sie es so schreiben würden, anstatt nur
while (!blocker.isReleasable() &&
!blocker.block());
Ist es nur eine Wahl der Semantik / Lesbarkeit, da Sie das erste Konstrukt als lesen könnten do "nothing" while "conditions"
? Oder fehlt mir ein zusätzlicher Vorteil?
java
while-loop
do-while
Erik Vesteraas
quelle
quelle
while
Version ein Update einer CAS-Variablen ?do {} while()
eine JIT-Optimierung vermieden wird, die von den Benutzernwhile()
verwendet wird. Die while-Anweisungen sind semantisch äquivalent, daher muss der Unterschied in der Implementierung der JVM liegen.ForkJoinPool
nutztcompareAndSwap...
aussun.misc.Unsafe
und die meisten Vorkommen vondo {} while (...)
inForkJoinPool
können - wie in anderen Antworten erwähnt - durch diesen Kommentar unter der Überschrift Style Notes erklärt werden:Die Wahl, eine-
while
Schleife mit einem leeren Körper zu schreiben,do {} while (condition)
scheint jedoch eine meist stilistische Wahl zu sein. Dies ist vielleicht klarer inHashMap
, was zufällig in Java 8 aktualisiert wurde.In Java 7 finden
HashMap
Sie Folgendes:while (index < t.length && (next = t[index++]) == null) ;
Während sich ein Großteil des Codes geändert hat, ist klar, dass der Ersatz in Java 8 folgender ist:
do {} while (index < t.length && (next = t[index++]) == null);
Die erste Version hat die Schwäche, dass das Löschen des einzelnen Semikolons die Bedeutung des Programms abhängig von der folgenden Zeile ändern würde.
Wie unten zu sehen ist, unterscheidet sich der von
while (...) {}
und generierte Bytecodedo {} while (...);
geringfügig, darf sich jedoch in keiner Weise auf die Ausführung auswirken.Java-Code:
class WhileTest { boolean condition; void waitWhile() { while(!condition); } void waitDoWhile() { do {} while(!condition); } }
Generierter Code:
class WhileTest { boolean condition; WhileTest(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return void waitWhile(); Code: 0: aload_0 1: getfield #2 // Field condition:Z 4: ifne 10 7: goto 0 10: return void waitDoWhile(); Code: 0: aload_0 1: getfield #2 // Field condition:Z 4: ifeq 0 7: return }
quelle
Abgesehen von potenziellen Leistungsvorteilen ergibt sich ein klarer Vorteil für die Lesbarkeit.
Da
while (X) ;
das nachfolgende Semikolon auf den ersten Blick nicht immer offensichtlich ist, können Sie verwirrt sein, wenn Sie glauben, dass sich die folgenden Anweisungen in der Schleife befinden. Zum Beispiel:while (x==process(y)); if (z=x) { // do stuff. }
Es wäre sehr leicht, das Obige falsch zu verstehen, wenn die if-Anweisung in der Schleife enthalten wäre, und selbst wenn Sie es richtig gelesen hätten, wäre es leicht zu glauben, dass es sich um einen Programmierfehler handelt und das if in der Schleife sein sollte.
Dabei
do {} while(X);
ist sofort auf einen Blick klar, dass die Schleife keinen Körper hat.quelle
while (x==process(y)) {}
? Ich denke, das wäre fast so klar wie diedo ... while()
Lösung.do {} while
Konstruktion Schlüsselwörter zwischen den Klammern enthält, wird die Trennung sauberer. Selbst in diesem einfachen Beispiel haben wir bereits 4 Klammern nacheinander)){}
- Sie können leicht erkennen, dass diese Zahl zunehmen könnte, wenn sie komplizierter wird{}
.Wenn Sie einen Kommentar über dem Code lesen, wird erwähnt, dass ...
Wenn der Aufrufer kein a ist
ForkJoinTask
, entspricht diese Methode verhaltensmäßigwhile (!blocker.isReleasable()) if (blocker.block()) return; }
Es ist also nur eine andere Form, den obigen Code in einem anderen Teil zu implementieren ... !!
In Style Notes wird erwähnt, dass,
Wenn die Implementierung von ManagedLocker # isReleasable angezeigt wird , wird die Sperre aktualisiert und zurückgegeben,
true
wenn keine Blockierung erforderlich ist.Interpretation :
Leer, während Schleifen verwendet werden, um einen Interrupt bereitzustellen, bis eine Bedingung auf wahr / falsch zurückgesetzt wird.
Hier
do { } while(!...)
ist ein Blocker / Unterbrechung , bisblocker.block()
sein wird ,true
wennblocker.isReleasable()
istfalse
. Die Schleife setzt die Ausführung fort, solange sieblocker
nicht freigebbar ist (!blocker.isReleasable()
) undblocker
nicht blockiert ist !! Die Ausführung wird außerhalb der Schleife sein, sobaldblocker.block()
sie auf true gesetzt ist.Beachten Sie, dass
do{ } while(...)
die CAS-Variable nicht aktualisiert wird, aber garantiert, dass das Programm wartet, bis die Variable aktualisiert wird (erzwingen Sie, bis die Variable aktualisiert wird).quelle
while(!cas...)
keine Aktualisierung erzwungen werden würde? Dass es einen tatsächlichen technischen Unterschied gibt, wie der Bytecode zeigt? Ich frage mich, ob das Betrachten von isReleasable eine Ablenkung ist, da es viele Stellen gibt, an denen es für tatsächliche CAS-Variablen wie diese verwendet wird:do {} while (!U.compareAndSwapLong(...));
isReleasable()
es eine Ablenkung ist. Siehe die Interpretation bearbeiten.while(!cas...);
angesprochen, ob eine Aktualisierung einer CompareAndSwap-Variablen erzwungen werden kann oder ob diesdo {} while (!cas...);
erforderlich ist, dh ob es einen tatsächlichen technischen Unterschied gibt oder nicht.Sie können so etwas ganz einfach machen mit:
if(true){ //Do nothing ... }
quelle