ProgramaciónDesarrollador Backend

¿Cómo funciona el mecanismo synchronized en Java? ¿Cuándo aplicarlo y qué trampas existen al sincronizar el acceso a recursos?

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

Historia de la pregunta:

Desde la aparición de Java, los desarrolladores se han enfrentado al problema del acceso concurrente a recursos compartidos. Para solucionarlo, se introdujeron primitivos de sincronización de alto nivel, siendo el más destacado el modificador clave synchronized.

Problema:

Sin sincronización en aplicaciones multihilo, los recursos compartidos pueden dañarse: surge una carrera de datos, el estado del objeto se vuelve impredecible.

Solución:

synchronized permite organizar un monitor para un método o bloque de código, asegurando que solo un hilo tenga acceso en un momento dado a la sección crítica. La sincronización de hilos puede realizarse a nivel de método o de bloque.

Ejemplo de bloqueo de objeto:

public class Counter { private int count = 0; public synchronized void increment() { count++; } public int getCount() { return count; } }

También se pueden sincronizar bloques:

public void safeIncrement() { synchronized(this) { count++; } }

Características clave:

  • La sincronización a nivel de método es equivalente a la sincronización a nivel de this
  • Para métodos estáticos, la sincronización se realiza por objeto-clase
  • Es necesario minimizar el área de la sección crítica

Preguntas engañosas.

¿Cuál es la diferencia entre un método synchronized y un bloque synchronized?

Un método synchronized bloquea todo el método para el objeto actual (this) o la clase (si el método es static). Un bloque permite sincronizar solo la parte necesaria del código y elegir cualquier objeto para el bloqueo.

¿Pueden dos hilos diferentes entrar simultáneamente a dos métodos synchronized diferentes de un mismo objeto?

No, si los métodos están sincronizados en un mismo monitor (this). Si utilizan monitores diferentes, entonces sí.

¿Afecta el modificador synchronized la visibilidad de las variables entre hilos?

Sí, entrar en un bloque synchronized invalida las cachés de los hilos y actualiza los valores de las variables (relación happens-before).

Errores típicos y anti-patrones

  • Sincronización en un objeto demasiado "amplio" (por ejemplo, en String o en objeto-clase)
  • Ejecución prolongada de código dentro de un bloque sincronizado
  • Mezcla de acceso a un mismo recurso a través de bloques synchronized y secciones no sincronizadas

Ejemplo de la vida

Caso negativo

Un desarrollador sincroniza métodos estáticos de la clase en el objeto de la instancia, lo que no garantiza la corrección al utilizar diferentes instancias.

Ventajas:

  • Implementación simple

Desventajas:

  • Carreras de datos inesperadas entre hilos
  • Errores difíciles de detectar

Caso positivo

Todos los métodos que utilizan un recurso compartido están sincronizados en un único objeto-monitor, la sección crítica es mínima.

Ventajas:

  • Los hilos trabajan con datos consistentes
  • Mínima bloqueo

Desventajas:

  • Más difícil de mantener y analizar bloqueos mutuos (deadlock), especialmente con un gran número de objetos sincronizados