¿Existe alguna ventaja en utilizar un método sincronizado en lugar de un bloque sincronizado?

Resuelto Warrior asked hace 15 años • 23 respuestas

¿Alguien puede decirme la ventaja del método sincronizado sobre el bloque sincronizado con un ejemplo?

Warrior avatar Feb 22 '09 10:02 Warrior
Aceptado

¿Alguien puede decirme la ventaja del método sincronizado sobre el bloque sincronizado con un ejemplo? Gracias.

No existe una ventaja clara de utilizar el método sincronizado sobre el bloque.

Quizás la única (pero no lo llamaría una ventaja) es que no es necesario incluir la referencia del objeto this.

Método:

public synchronized void method() { // blocks "this" from here.... 
    ...
    ...
    ...
} // to here

Bloquear:

public void method() { 
    synchronized( this ) { // blocks "this" from here .... 
        ....
        ....
        ....
    }  // to here...
}

¿Ver? Ninguna ventaja en absoluto.

Sin embargo, los bloques tienen ventajas sobre los métodos, principalmente en la flexibilidad porque puedes usar otro objeto como bloqueo, mientras que sincronizar el método bloquearía todo el objeto.

Comparar:

// locks the whole object
... 
private synchronized void someInputRelatedWork() {
    ... 
}
private synchronized void someOutputRelatedWork() {
    ... 
}

vs.

// Using specific locks
Object inputLock = new Object();
Object outputLock = new Object();

private void someInputRelatedWork() {
    synchronized(inputLock) { 
        ... 
    } 
}
private void someOutputRelatedWork() {
    synchronized(outputLock) { 
        ... 
    }
}

Además, si el método crece, aún puedes mantener separada la sección sincronizada:

 private void method() {
     ... code here
     ... code here
     ... code here
    synchronized( lock ) { 
        ... very few lines of code here
    }
     ... code here
     ... code here
     ... code here
     ... code here
}
OscarRyz avatar Feb 22 '2009 03:02 OscarRyz

La única diferencia real es que un bloque sincronizado puede elegir con qué objeto se sincroniza. Un método sincronizado solo puede usar 'this'(o la instancia de clase correspondiente para un método de clase sincronizado). Por ejemplo, estos son semánticamente equivalentes:

synchronized void foo() {
  ...
}

void foo() {
    synchronized (this) {
      ...
    }
}

Este último es más flexible ya que puede competir por el bloqueo asociado de cualquier objeto, a menudo una variable miembro. También es más granular porque podría ejecutar código simultáneo antes y después del bloque, pero aún dentro del método. Por supuesto, también podría utilizar un método sincronizado refactorizando el código concurrente en métodos separados no sincronizados. Utilice el que haga que el código sea más comprensible.

jcrossley3 avatar Feb 22 '2009 03:02 jcrossley3

Método sincronizado

Ventajas:

  • Su IDE puede indicar los métodos sincronizados.
  • La sintaxis es más compacta.
  • Obliga a dividir los bloques sincronizados en métodos separados.

Contras:

  • Se sincroniza con esto y, por lo tanto, permite que personas externas también lo sincronicen.
  • Es más difícil mover código fuera del bloque sincronizado.

Bloque sincronizado

Ventajas:

  • Permite usar una variable privada para el bloqueo y así forzar que el bloqueo permanezca dentro de la clase.
  • Los bloques sincronizados se pueden encontrar buscando referencias a la variable.

Contras:

  • La sintaxis es más complicada y, por tanto, hace que el código sea más difícil de leer.

Personalmente prefiero usar métodos sincronizados con clases enfocadas solo en lo que necesita sincronización. Esta clase debe ser lo más pequeña posible para que sea fácil revisar la sincronización. Otros no deberían preocuparse por la sincronización.

iny avatar Feb 22 '2009 07:02 iny

La principal diferencia es que si usas un bloque sincronizado puedes bloquear un objeto distinto a este , lo que permite ser mucho más flexible.

Suponga que tiene una cola de mensajes y varios productores y consumidores de mensajes. No queremos que los productores interfieran entre sí, pero los consumidores deberían poder recuperar mensajes sin tener que esperar a los productores. Entonces simplemente creamos un objeto.

Object writeLock = new Object();

Y de ahora en adelante, cada vez que un productor quiera agregar un nuevo mensaje, simplemente lo fijaremos:

synchronized(writeLock){
  // do something
}

Por lo tanto, los consumidores aún podrán leer y los productores quedarán bloqueados.

cdecker avatar Feb 22 '2009 03:02 cdecker