Reentrada de bloques sincronizados
Reentrada de bloques sincronizados
Una vez que un hilo ha entrado en un bloque sincronizado, se dice que el hilo “tiene el bloqueo” sobre el objeto monitor en el que está sincronizado el bloque sincronizado. Si el hilo llama a otro método que llama de vuelta al primer método con el bloque sincronizado dentro, el hilo que tiene el bloqueo puede volver a entrar en el bloque sincronizado. No está bloqueado solo porque un hilo (él mismo) tenga el bloqueo. Solo si un hilo diferente tiene el bloqueo. Veamos el ejemplo:
1public class MiClase {2
3 List<String> elementos = new ArrayList<String>();4
5 public int contar() {6 if(elementos.size() == 0) {7 return 0;8 }9 synchronized(this) {10 elementos.remove(0);11 return 1 + contar();12 }13 }14}
Nos concentremos en cómo dentro del bloque sincronizado dentro del método contar()
se llama al método contar()
recursivamente. Así, el hilo que llama a contar()
puede eventualmente entrar en el mismo bloque sincronizado múltiples veces. Esto está permitido y es posible.
Tengamos en cuenta, sin embargo, que los diseños donde un hilo entra en múltiples bloques sincronizados pueden llevar a un bloqueo de monitor anidado si no diseñamos el código cuidadosamente.
Puntos importantes sobre la sincronización en Java
La sincronización en Java es una herramienta poderosa para manejar la concurrencia y evitar condiciones de carrera. Sin embargo, es importante usarla con cuidado y entender sus implicaciones:
- Usar bloques sincronizados para proteger secciones críticas de código que acceden a recursos compartidos.
- Mantener los bloques sincronizados lo más pequeños posible para minimizar el impacto en el rendimiento.
- Tener cuidado al sincronizar en objetos
String
o envolturas de tipos primitivos. - Considerar alternativas como
ReadWriteLock
,Semaphore
, o variablesvolatile
para casos de uso más específicos.
Recordemos, la sincronización es solo una parte de la programación concurrente en Java. Para aplicaciones más complejas, debemos considerar usar las utilidades de concurrencia de alto nivel proporcionadas por el paquete java.util.concurrent
.