10 Stimmen

Ist eine Synchronisierung beim Lesen erforderlich, wenn keine Konflikte auftreten können?

Beachten Sie den nachstehenden Code Sniper:

package sync;

public class LockQuestion {
    private String mutable;

    public synchronized void setMutable(String mutable) {
        this.mutable = mutable;
    }

    public String getMutable() {
        return mutable;
    }   
}

Zum Zeitpunkt Time1 wird Thread1 die Variable "mutable" aktualisieren. Die Synchronisierung ist im Setter erforderlich, um den Speicher vom lokalen Cache in den Hauptspeicher zu leeren. Zum Zeitpunkt Time2 (Time2 > Time1, keine Thread-Konkurrenz) liest Thread Thread2 den Wert der Variable mutable.

Frage ist - muss ich synchronized vor getter setzen? Sieht aus wie dies wird keine Probleme verursachen - Speicher sollte aktuell sein und Thread2's lokalen Cache-Speicher sollte ungültig & aktualisiert von Thread1, aber ich bin nicht sicher.

9 Stimmen

Threading in Java ist definiert als passiert-vor Beziehungen. Versuchen Sie nicht, in Begriffen wie "flushing caches" zu denken, denn das wäre falsch. Zum einen sind die Optimierungen des Compilers wichtig. Selbst wenn das Flushing von Caches ein genaues Modell wäre, wäre die Reihenfolge der Aktualisierungen nicht garantiert, wenn das verwiesene Objekt veränderbar ist. (Bis zur Spezifikation 1.5 verwendete die Spezifikation ein Flushing-Caches-Modell, das jedoch nicht implementierbar war).

0voto

MSN Punkte 51308

Dies wird wahrscheinlich nie zu einem falschen Verhalten führen, aber wenn Sie nicht auch die Reihenfolge garantieren, in der die Threads starten, können Sie nicht unbedingt garantieren, dass der Compiler das Lesen in Thread2 nicht vor dem Schreiben in Thread1 umgestellt hat. Genauer gesagt, die gesamte Java-Laufzeitumgebung muss lediglich gewährleisten, dass die Threads so ausgeführt werden, als ob sie seriell laufen würden . Solange also der Thread bei serieller Ausführung unter Optimierungen die gleiche Ausgabe hat, kann der gesamte Sprachstapel (Compiler, Hardware, Sprachlaufzeit) so ziemlich alles tun, was er will. Einschließlich der Möglichkeit für Thread2, das Ergebnis von LockQuestion.getMutable() .

In der Praxis würde es mich sehr überraschen, wenn dies jemals geschehen würde. Wenn Sie sicherstellen wollen, dass dies nicht passiert, sollten Sie LockQuestion.mutable erklärt werden als final und werden im Konstruktor initialisiert. Oder verwenden Sie die folgende Redewendung :

private static class LazySomethingHolder {
  public static Something something = new Something();
}

public static Something getInstance() {
  return LazySomethingHolder.something;
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X