¿Existe alguna ventaja en utilizar un método sincronizado en lugar de un bloque sincronizado?
¿Alguien puede decirme la ventaja del método sincronizado sobre el bloque sincronizado con un ejemplo?
¿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
}
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.
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.
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.