Frage

Wenn ein Klassenfeld über eine Getter-Methode von mehreren Threads zugegriffen wird, wie halten Sie Thread-Sicherheit? Ist das Schlüsselwort synchronized ausreichend?

Ist das sicher:

public class SomeClass {
    private int val;

    public synchronized int getVal() {
        return val;
    }

    private void setVal(int val) {
        this.val = val;
    }
}

oder hat die Setter weitere Komplikationen einführen?

War es hilfreich?

Lösung

Wenn Sie auch hier ‚synchronisiert‘ auf dem Setter verwenden, wird dieser Code THREAD. Es kann jedoch nicht ausreichend granular sein; wenn Sie 20 Getter und Setter haben und sie sind alle synchronisiert, können Sie einen Synchronisationsengpass werden zu schaffen.

In diesem speziellen Fall mit einem einzigen int-Variable, dann ist die ‚synchronisiert‘ eliminiert und die Kennzeichnung das int Feldes ‚volatile‘ wird auch die Sichtbarkeit gewährleisten (jeder Thread wird den neuesten Wert von ‚val‘ sehen, wenn die Getter Aufruf), aber es kann nicht für Ihre Bedürfnisse synchronisiert genug werden. Zum Beispiel erwartet

 int old = someThing.getVal();
 if (old == 1) {
    someThing.setVal(2);
 }

gesetzt val auf 2, wenn und nur wenn es bereits 1 falsch ist. Dafür benötigen Sie eine externe Sperre, oder eine atomare Vergleichs- und Set-Methode.

ich dringend empfehlen Sie lesen Java Concurrency in der Praxis von Brian Goetz et al , es hat die beste Abdeckung von Java Concurrency-Konstrukten.

Andere Tipps

Neben Cowan Kommentar , könnten Sie tun, um die folgenden für eine vergleichen und zu speichern:

synchronized(someThing) {
    int old = someThing.getVal();
    if (old == 1) {
        someThing.setVal(2);
    }
}

Das funktioniert, weil die Sperre über eine synchronisierte Methode definierte implizit das gleiche wie die Sperre des Objekts ist ( Java-Sprache spec ).

Von meinem Verständnis sollte man auf synchronisiert das Gerät mit beiden Getter und den Setter-Methoden, und das ist ausreichend.

Edit: Hier ist ein Link rel="nofollow zu einige weitere Informationen zur Synchronisierung und was nicht.

Wenn Ihre Klasse nur eine Variable enthält, dann eine andere Art und Weise Thread-Sicherheit zu erreichen, ist das bestehende Objekt Atomicinteger zu verwenden.

public class ThreadSafeSomeClass {

    private final AtomicInteger value = new AtomicInteger(0);

    public void setValue(int x){
         value.set(x);
    }

    public int getValue(){
         return value.get();
    }

}

Wenn Sie jedoch zusätzliche Variablen hinzufügen, so dass sie abhängig sind (Zustand einer Variablen hängt von dem Zustand eines anderen), dann wird Atomicinteger nicht funktionieren.

den Vorschlag Echoing "Java Concurrency in Practice" zu lesen.

Für einfache Objekte kann dies ausreichen. In den meisten Fällen sollten Sie das Schlüsselwort synchronized vermeiden, weil Sie in einem Synchronisations Deadlock führen kann.

Beispiel:

public class SomeClass {

  private Object mutex = new Object();
  private int    val   = -1; // TODO: Adjust initialization to a reasonable start
                             //       value
  public int getVal() {
    synchronized ( mutex ) {
      return val;
    }
  }

  private void setVal( int val ) {
    synchronized ( mutex ) {
      this.val = val;
    }
  }
}

Stellt sicher, dass nur ein Thread liest oder schreibt in die lokale Instanz Mitglied.

das Buch "Concurrent Programming in Java (tm): Design-Prinzipien und Patterns (Java (Addison-Wesley))" lesen, vielleicht http://java.sun.com/docs/books/tutorial/essential/concurrency/index.html ist auch hilfreich ...

Synchronisation existiert gegen Gewindeinterferenz und Speicherkonsistenzfehler zu schützen. Durch die Synchronisation auf dem getVal (), wird der Code gewährleistet, dass auch andere Methoden auf synchronisierte Someclass auch nicht zur gleichen Zeit ausgeführt werden. Da es keine anderen synchronisierten Methoden sind, bietet es nicht viel Wert. Beachten Sie auch, dass liest und schreibt auf Primitiven Atom-Zugang. Das bedeutet, dass bei sorgfältiger Programmierung, man nicht den Zugriff auf das Feld synchronisieren muß.

Lesen Sie Sychronisierungsoperationen .

Nicht wirklich sicher, warum dies auf -3 fallen gelassen wurde. Ich bin zusammenfassend einfach, was die Synchronisation Tutorial von Sun sagt (wie auch meine eigene Erfahrung).

  

Mit einfachen Atom variablen Zugriff   effizienter als diese den Zugriff auf   Variablen durch synchronisierte Code,   aber erfordert mehr Sorgfalt durch die   Programmierer Speicherkonsistenz zu vermeiden   Fehler. Ob der zusätzliche Aufwand ist   lohnt, hängt von der Größe und   Komplexität der Anwendung.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top