En el ejemplo, el método A y el método B son métodos de instancia (a diferencia de los métodos estáticos). Poner synchronized
un método de instancia significa que el hilo debe adquirir el bloqueo (el "bloqueo intrínseco") en la instancia del objeto al que se llama el método antes de que el hilo pueda comenzar a ejecutar cualquier código en ese método.
Si tiene dos métodos de instancia diferentes marcados como sincronizados y diferentes subprocesos llaman a esos métodos simultáneamente en el mismo objeto, esos subprocesos competirán por el mismo bloqueo. Una vez que un subproceso obtiene el bloqueo, todos los demás subprocesos quedan excluidos de todos los métodos de instancia sincronizados en ese objeto.
Para que los dos métodos se ejecuten simultáneamente, tendrían que usar diferentes bloqueos, como este:
class A {
private final Object lockA = new Object();
private final Object lockB = new Object();
public void methodA() {
synchronized(lockA) {
//method A
}
}
public void methodB() {
synchronized(lockB) {
//method B
}
}
}
donde la sintaxis del bloque sincronizado permite especificar un objeto específico en el que el subproceso en ejecución necesita adquirir el bloqueo intrínseco para ingresar al bloque.
Lo importante a entender es que a pesar de que estamos poniendo una palabra clave "sincronizada" en métodos individuales, el concepto central es el bloqueo intrínseco detrás de escena.
Así es como el tutorial de Java describe la relación:
La sincronización se basa en una entidad interna conocida como bloqueo intrínseco o bloqueo de monitor. (La especificación de API a menudo se refiere a esta entidad simplemente como un "monitor".) Los bloqueos intrínsecos juegan un papel en ambos aspectos de la sincronización: imponer el acceso exclusivo al estado de un objeto y establecer relaciones antes de que sean esenciales para la visibilidad.
Cada objeto tiene un bloqueo intrínseco asociado. Por convención, un hilo que necesita acceso exclusivo y consistente a los campos de un objeto tiene que adquirir el bloqueo intrínseco del objeto antes de acceder a ellos, y luego liberar el bloqueo intrínseco cuando se hace con ellos. Se dice que un subproceso posee el bloqueo intrínseco entre el momento en que adquirió el bloqueo y lo liberó. Mientras un hilo posea un bloqueo intrínseco, ningún otro hilo puede adquirir el mismo bloqueo. El otro hilo se bloqueará cuando intente adquirir el bloqueo.
El propósito del bloqueo es proteger los datos compartidos. Usaría bloqueos separados como se muestra en el código de ejemplo anterior solo si cada bloqueo protegía a diferentes miembros de datos.