2012-01-29 21 views
12

He leído en algún lugar que synchronized(this) se debe evitar para various reasons. Sin embargo, algo de código respetable que me encontré utiliza la siguiente en el constructor:¿Cuál es la diferencia entre synchronized (this) y synchronized (ClassName.class)?

public SomeClass(Context context) { 
    if (double_checked_lock == null) { 
    synchronized (SomeClass.class) { 
     if (double_checked_lock == null) { 
     // some code here 
     } 
    } 
    } 
} 

¿Existe realmente una diferencia entre synchronized(this) y synchronized(SomeClass.class)?

Respuesta

23

synchronized(this) se sincroniza en el objeto actual, por lo que solo un subproceso puede acceder a cada instancia, pero diferentes subprocesos pueden acceder a instancias diferentes. P.ej. puedes tener una instancia por hilo.

Esto suele ser útil para evitar que varios subprocesos actualicen un objeto al mismo tiempo, lo que podría crear un estado incoherente.

synchronized(SomeClass.class) está sincronizado en la clase del objeto actual (u otra clase si se quisiera) de modo que sólo un hilo a la vez puede acceder cualquier instancias de esa clase.

Esto podría utilizarse para proteger los datos que se comparten en todas las instancias de una clase (una caché de instancia, quizás) de pasar a un estado incoherente.

+1

+1. Esto proporciona más claridad entre clase y bloqueo de objeto. No encontré nada mejor que esto. * Corto y simple de entender * – Ravi

5

this es diferente para cada instancia.
ClassName.class no lo es.

Por lo tanto, synchronized(this) permitirá que varias instancias se ejecuten simultáneamente.

3

La palabra clave synchronized, cuando se aplica a un class se bloquea en la clase, y cuando se aplica a this se bloquea en la instancia del objeto actual. De la Especificación del lenguaje Java, sección 8.4.3.6, 'synchronized Methods':

Un método sincronizado adquiere un monitor (§17.1) antes de que se ejecute. Para un método de clase (estático), se usa el monitor asociado con el objeto de Clase para la clase del método. Para un método de instancia, se usa el monitor asociado con esto (el objeto para el cual se invocó el método).

1

Estos son 2 objeto diferente para bloquear en: 'esto' se refieren a contexto instancia actual, por lo que crean varias instancias no tendrán ningún efecto si, por ejemplo, cada hilo usando una instancia diferente y bloquear en él. 'esto' puede referirse solo en contexto no estático.
la 'clase' es un miembro estático de la clase Java y hay exactamente una instancia de la misma. Puede bloquearlo en contexto estático y no estático.

1

synchronized(this) se sincroniza en la instancia del objeto.

synchronized(SomeClass.class) usa la instancia del objeto Class que representa SomeClass, que es global para todas las instancias en el mismo cargador de clases.

Por lo tanto, estos son constructos diferentes con semántica diferente.

Al usar synchronized solo, o como un modificador de método, también se sincroniza en el semáforo de la instancia, que normalmente se usa para evitar la contención entre varios subprocesos que acceden a esa instancia como un recurso compartido (es decir, una Lista).

El hilo que refiere indica que es una mejor práctica usar una instancia privada, ya que la sincronización directa en su instancia de objeto puede ser peligrosa. Para eso usarías:

class MySharedResourceClass { 

    private SomeClass lock = new SomeClass(); 

    public doSomething() { 
     synchronized (lock) { 
      // Do something here 
     } 
    } 
} 
2

Cada objeto de Java puede tener un candado. Este bloqueo se puede mantener como mucho un hilo a la vez, cualquier otro hilo tiene que esperar para obtener el bloqueo del mismo objeto.

  • synchronized(this) adquiere el bloqueo de la instancia this para el subproceso actual. El método puede ejecutarse en paralelo en diferentes instancias (diferentes valores para esto y por lo tanto cerraduras diferentes)

  • synchronized(SomeClass.class) adquiere el bloqueo del objeto de clase global de SomeClass. Solo se puede ejecutar una instancia del método ya que todas las instancias de objetos se bloquean en el mismo objeto global (mismo bloqueo).

Cuestiones relacionadas