2013-04-19 16 views
5

Diese Frage ist etwas Fortsetzung und Erweiterung dieser, wie ich glaube, perfekt Frage: How does assigning to a local variable help here?Zugriff auf flüchtige Felder durch lokale Variablen

diese Frage basiert auf Item 71 von Effective Java, wo es wird vorgeschlagen, die Leistung zu beschleunigen durch lokalen Variable in Zweck volatile Feldzugriff Einführung:

private volatile FieldType field; 
FieldType getField() { 
    FieldType result = field; 
    if (result == null) { // First check (no locking) 
     synchronized(this) { 
     result = field; 
     if (result == null) // Second check (with locking) 
      field = result = computeFieldValue(); 
     } 
    } 
    return result; 
} 

So meine Frage ist häufiger:

sollten wir immer Zugriff auf volatile Felder durch Zuordnung ihrer Werte zu lokalen Variablen?(um die beste Leistung zu archivieren).

I.e. einige Idiom:

  1. haben wir einige volatile Feld, nennen es nur volatileField;

  2. wenn wir seinen Wert lesen wollen in Multi-Thread-Methode, wir sollten:

    1. lokalen Variable mit dem gleichen Typ erstellen: localVolatileVariable
    2. assign Wert von flüchtigem Feld: localVolatileVariable = volatileField
    3. Lese Wert aus diesem lokalen Kopie, zB:

      if (localVolatileVariable != null) { ... } 
      
+0

Wie unterscheidet sich diese Frage von der, auf die Sie verlinken? Es scheint, dass Sie eine Antwort auf eine Situation haben möchten, die breiter ist als das Szenario "lazy-loaded Field initialisieren" des dort gezeigten Codes (und hier). Aber dann kann die Antwort nicht mehr sein als "es kommt darauf an", fürchte ich. – Thilo

+0

Es ist anders, dass ich nur verstehen will: ist diese Optimierung nur für den speziellen Fall anwendbar, der in "Item 71" beschrieben wird, oder ist es ein gewöhnlicher Ansatz für das Lesen von "flüchtigen" Feldern? – Andremoniy

Antwort

3

Sie müssen flüchtige Variablen zu lokalen Feldern zuordnen, wenn Sie planen, irgendeine Art von mehrstufiger Logik (vorausgesetzt natürlich, dass das Feld veränderbar ist).

zum Beispiel:

volatile String _field; 

public int getFieldLength() { 
    String tmp = _field; 
    if(tmp != null) { 
    return tmp.length(); 
    } 
    return 0; 
} 

, wenn Sie nicht eine lokale Kopie _field, dann könnte der Wert ändern zwischen dem „if“ Test und der „length()“ Methodenaufruf, was möglicherweise in einem verwendet haben NPE.

Dies ist außerdem der offensichtliche Vorteil einer Geschwindigkeitsverbesserung, indem nicht mehr als ein flüchtiger Lesevorgang ausgeführt wird.

1

Es gibt zwei Seiten einer Münze.

Auf der einen Seite funktioniert die Zuweisung zu einem flüchtigen Speicher wie eine Speicherbarriere und es ist sehr unwahrscheinlich, dass JIT die Zuweisung mit dem Aufruf computeFieldValue neu anordnet.

Auf der anderen Seite bricht dieser Code in der Theorie JMM. Denn aus irgendwelchen Gründen kann einige JVM computeFieldValue mit Zuweisung neu ordnen und Sie sehen teilweise initialisiertes Objekt. Dies ist möglich, solange die Variable read nicht mit der Variablen write geschrieben wird.

field = result = computeFieldValue(); 

geschieht nicht vor

if (result == null) { // First check (no locking) 

Solange Java-Code sein soll „einmal schreiben laufen überall“ DCL eine schlechte Praxis und sollte vermieden werden. Dieser Code ist kaputt und kein Punkt der Überlegung.

Wenn Sie mehrere Lesevorgänge einer flüchtigen Variablen in einer Methode durchführen, indem Sie sie zuerst einer lokalen Variablen zuweisen, minimieren Sie solche Lesevorgänge, die teurer sind. Aber ich denke nicht, dass Sie einen Leistungsschub bekommen. Dies dürfte eine theoretische Verbesserung sein. Eine solche Optimierung sollte JIT überlassen werden und ist kein Punkt der Überlegungen des Entwicklers. Ich stimme zu this.

+0

Zum einen die Zuordnung zu einem volatilen Werk -> er schreibt nicht zu einem volatilen, er liest einen. – Eugene

+0

"field = result = computeFieldValue()" hier schreibt er. Dies ist eine Variation eines klassischen DCL Anti-Patterns. – Mikhail

+0

fyi, das DCL-Muster, das im OP gezeigt wird, ist _nicht_ gebrochen (es ist die "feste" Version). nicht sicher von Ihrem Post, ob Sie implizieren, dass es korrekt ist oder nicht. – jtahlborn

0

Anstatt TWO liest von einer flüchtigen Variablen, macht er nur einen. Das Lesen von volatile ist wahrscheinlich etwas langsamer als die übliche Variable. Aber selbst wenn, reden wir hier über Nano-Sekunden.

+0

Nun, aber Joshua Bloch spricht über 25% bessere Leistung auf seiner Maschine :) – Andremoniy

+1

@Andremoniy das war vor einiger Zeit Das hat er geschrieben. Und 25% von 1 Nanosekunden ist immer noch sehr wenig. Zu wenig für mich. – Eugene

Verwandte Themen