El modificador synchronized
es realmente una idea mala y debe evitarse a toda costa.Creo que es encomiable que Sun haya tratado de hacer que el bloqueo sea un poco más fácil de lograr, pero synchronized
solo causa más problemas de los que merece la pena.
El problema es que un método synchronized
es en realidad un azucar de sintaxis para obtener el bloqueo en this
y mantenerlo durante todo el proceso. Por lo tanto, public synchronized void setInstanceVar()
sería equivalente a algo como esto:
public void setInstanceVar() {
synchronized(this) {
instanceVar++;
}
}
Esto es malo por dos razones:
- Todos
synchronized
métodos dentro de la misma clase de uso de la misma cerradura, que el rendimiento se reduce
- Cualquiera puede obtener acceso a la cerradura, incluidos los miembros de otras clases.
No hay nada que me impida hacer algo como esto en otra clase:
MyClass c = new MyClass();
synchronized(c) {
...
}
Dentro de ese bloque synchronized
, estoy sosteniendo la cerradura que es requerido por todos los métodos synchronized
dentro MyClass
. Esto reduce aún más el rendimiento y dramáticamente aumenta las posibilidades de un punto muerto.
Un mejor enfoque es tener un lock
objeto dedicado y utilizar el bloque synchronized(...)
directamente:
public class MyClass {
private int instanceVar;
private final Object lock = new Object(); // must be final!
public void setInstanceVar() {
synchronized(lock) {
instanceVar++;
}
}
}
Como alternativa, puede utilizar la interfaz java.util.concurrent.Lock
y la implementación java.util.concurrent.locks.ReentrantLock
para lograr básicamente el mismo resultado (de hecho , es lo mismo en Java 6).
Aunque tenga cuidado con los operadores ++ y -, no son atómicos. Para estar seguro, intente usar clases de java.util.concurrent.atomic. – InverseFalcon
Las operaciones en enteros no son atómicas en Java. –
Puede modificar un int de diferentes subprocesos, obtener el almacenamiento en caché localizado en los subprocesos, tener la operación de lectura y escritura de sincronización de sincronización. El hecho de que los largos y los dobles lean y escriban como dos operaciones op (carga superior y carga más baja para obtener los 64 bits) no significa que los enteros se vuelvan súbitamente atómicos porque sufren de 1 menos problemas que no impiden la amenaza de los hilos. – Tatarize