2012-06-23 4 views
6

Mögliche Duplizieren:
Avoid synchronized(this) in Java?Synchronisation auf "diesem" oder privaten Objekt in Java?

Was ist der Unterschied zwischen den beiden Teilen des Codes? Was sind Vor- und Nachteile von jedem?

1)

public class Example { 
private int value = 0; 

public int getNextValue() { 
    synchronized (this) { 
     return value++; 
    } 
} 
} 

2)

public class Example { 
private int value = 0; 

private final Object lock = new Object(); 

public int getNextValue() { 
    synchronized (lock) { 
     return value++; 
    } 
} 
} 
+2

Der zweite Ansatz ist fast immer besser (AFAIK) - aber warum? Welche negativen Auswirkungen hat die Sichtbarkeit von "diesem" (nur "das Objekt" von außen)? Wie kann "schlechter Code" eine Störung des Synchronisationsziels verursachen? –

+0

Ist Ihnen bekannt, dass 'pubilc synchronized int getNextValue() {...} 'genau dasselbe ist wie' public int getNextValue() {synchronized (this) {...}}'? – Miquel

Antwort

3

Der Hauptgrund, warum ich den zweiten Ansatz wählen würde, ist, dass ich nicht kontrollieren, was die Kunden mit den Instanzen meiner Klasse zu tun.

Wenn aus irgendeinem Grund, jemand eine Instanz meiner Klasse als Sperre verwenden entscheidet, werden sie mit der Synchronisationslogik innerhalb meiner Klasse stören:

class ClientCode { 
    Example exampleInstance; 

    void someMethod() { 
     synchronized (exampleInstance) { 
      //... 
     } 
    } 
} 

Wenn innerhalb meiner Example Klasse, ich m mit einer Sperre, die niemand sonst sehen kann, können sie meine Logik nicht stören und einen willkürlichen Mutex einführen, wie im obigen Szenario.

Zusammenfassend ist dies nur eine Anwendung des Information-Hiding-Prinzips.

0

Ich würde sagen, dass die zweite Methode ist besser. Betrachten Sie die folgende Situation:

public class Abc{ 

    private int someVariable; 

    public class Xyz { 
     //some method,synchronize on this 
    } 

     //some method, and again synchronize on this 


} 

In dieser Situation this ist nicht das gleiche in den beiden Methoden. Man ist eine Methode der inneren Klasse. Daher ist es besser, ein gemeinsames Objekt für die Synchronisation zu verwenden. Zum Beispiel synchronized (someVariable).

+0

Sie könnten jedoch 'synchronize (Abc.this)' verwenden. – Thilo

+0

Yup. Das ist auch die Alternative, aber die Frage ist "this", dh die aktuelle "Object" -Verweisung. Ich könnte mich allerdings irren, immer noch ein Anfänger. :-) –

+1

Der Java Concurrency in Practice Buch hatte diesen Fehler. –

3

Ich würde die zweite Option bevorzugen, wenn ich zwei verschiedene Aufgaben gleichzeitig ausführen müssen, die unabhängig voneinander sind.

z.B .:

public class Example { 
    private int value = 0; 
    private int new_value = 0; 
    private final Object lock1 = new Object(); 
    private final Object lock2 = new Object(); 

    public int getNextValue() { 
     synchronized (lock1) { 
      return value++; 
     } 
    } 

    public int getNextNewValue() { 
     synchronized (lock2) {    
      return new_value++; 
     } 
    } 
} 
0

Ich denke, es hängt wirklich von der Situation ab. Nehmen wir an, Ihre Klasse ist eine Unterklasse und die Superklasse hat eine Methode, die eine Synchronisation hat. Nehmen wir an, Sie arbeiten mit demselben Datensatz und möchten auch die Integrität Ihrer Methode erhalten. Dann definitiv Ansatz 1 ist, was Sie verwenden sollten.

Ansonsten zweiter Ansatz funktionieren würde besser auf, was Costi

erwähnt
+0

Ich stimme dir zu, aber in diesem Fall würde ich sagen, die Superklasse ist nicht ganz richtig gestaltet; es könnte eine "geschützte" Sperre bereitstellen, die ich in einer Unterklasse verwenden kann, ohne die gesamte Synchronisationslogik öffentlich verfügbar zu machen. –

+1

@CostiCiudatu stimme Ihnen vollkommen zu. Dies ist nur in Fällen der Fall, in denen Sie einige Klassen von der Codebasis eines anderen erben. Dies ist wahrscheinlich selten. – Vidyanand

+0

+1 für die gute Qualität Sarkasmus - 'Dies ist wahrscheinlich selten' :). Ich wollte nur betonen, dass dieser Ansatz * nicht * empfohlen wird, wenn Sie wählen können, aber nur der einzige verfügbare Weg in einigen Szenarien. –

Verwandte Themen