2012-06-23 7 views
6

Duplicar posible:
Avoid synchronized(this) in Java?Sincronización en "esto" o en un objeto privado en Java?

¿Cuál es la diferencia entre las dos piezas de código? ¿Cuáles son las ventajas y desventajas de cada uno?

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

El segundo enfoque es casi siempre mejor (que yo sepa) - pero ¿por qué? ¿Qué impactos negativos tiene la visibilidad de "esto" (solo "el objeto" desde el exterior)? ¿Cómo podría el "código incorrecto" causar interferencia con el objetivo de sincronización? –

+0

¿Sabía que 'pubilc synchronized int getNextValue() {...}' es exactamente igual que 'public int getNextValue() {synchronized (this) {...}}'? – Miquel

Respuesta

3

La razón principal por la que elegiría el segundo enfoque es que no controlo lo que los clientes hacen con las instancias de la clase.

Si, por alguna razón, alguien decide utilizar una instancia de mi clase como un bloqueo, interferirán con la lógica de sincronización dentro de mi clase:

class ClientCode { 
    Example exampleInstance; 

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

Si, dentro de mi clase Example, I' Usando un candado que nadie más puede ver, no pueden interferir con mi lógica e introducir un mutex arbitrario como en el escenario anterior.

En resumen, esta es solo una aplicación del principio de ocultamiento de información.

0

Yo diría que el segundo método es mejor. Considere la siguiente situación:

public class Abc{ 

    private int someVariable; 

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

     //some method, and again synchronize on this 


} 

En esta situación this no es el mismo en los dos métodos. Uno es un método de la clase interna. Por lo tanto, es mejor usar un objeto común para la sincronización. Por ejemplo, synchronized (someVariable).

+0

Sin embargo, podría usar 'synchronize (Abc.this)'. – Thilo

+0

Sí. Esa es también la alternativa, pero la pregunta es sobre 'esto', es decir, la referencia actual del 'Objeto'. Sin embargo, podría estar equivocado, aún soy un principiante. :-) –

+1

El libro de Java Concurrency in Practice tenía este error. –

3

Preferiría la segunda opción si necesito ejecutar dos tareas diferentes simultáneamente que son independientes entre sí.

ej .:

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

Creo que realmente depende de la situación. Digamos que tu clase es una subclase y la superclase tiene un método que tiene sincronización. Y digamos que está trabajando con el mismo conjunto de datos y desea mantener la integridad dentro de su método también. Entonces definitivamente el acercamiento 1 es lo que deberías estar usando.

De lo contrario segundo enfoque funcionaría mejor en base a lo mencionado Costi

+0

Estoy de acuerdo con usted, pero en este caso diría que la superclase no está diseñada de manera adecuada; podría proporcionar un bloqueo "protegido" que pueda usar en una subclase sin hacer que toda la lógica de sincronización esté disponible públicamente. –

+1

@CostiCiudatu Totalmente de acuerdo con usted en eso. Esto solo ocurre cuando heredas algunas clases de la base de código de otra persona. Esto es probablemente raro – Vidyanand

+0

+1 por el sarcasmo de buena calidad - 'Esto es probablemente raro' :). Mi punto era solo enfatizar que este enfoque * no * se recomienda cuando puedes elegir, pero es la única forma disponible en algunos escenarios. –

Cuestiones relacionadas