Si tengo 2 métodos sincronizados en la misma clase, pero cada uno accede a diferentes variables, ¿pueden 2 hilos acceder a esos 2 métodos al mismo tiempo? ¿Se produce el bloqueo en el objeto o se vuelve tan específico como las variables dentro del método sincronizado?
Ejemplo:
class X {
private int a;
private int b;
public synchronized void addA(){
a++;
}
public synchronized void addB(){
b++;
}
}
¿Pueden 2 hilos acceder a la misma instancia de rendimiento de clase X x.addA(
) y x.addB()
al mismo tiempo?
synchronized (this)
bloque alrededor del cuerpo del método. El objeto "this" no se bloquea, sino que el objeto "this" se usa como mutex y se impide que el cuerpo se ejecute simultáneamente con otras secciones de código también sincronizadas en "this". No tiene ningún efecto en otros campos / métodos de "esto" que no están sincronizados.a
yb
fueran objetos, por ejemplo,Integer
s, estaba sincronizando en instancias que está reemplazando con diferentes objetos al aplicar el++
operador.Sincronizado en la declaración del método está el azúcar sintáctico para esto:
En un método estático, es azúcar sintáctico para esto:
Creo que si los diseñadores de Java supieran lo que se entiende ahora sobre sincronización, no habrían agregado el azúcar sintáctico, ya que la mayoría de las veces conduce a malas implementaciones de concurrencia.
fuente
De "Los Tutoriales Java ™" sobre métodos sincronizados :
De "The Java ™ Tutorials" en bloques sincronizados :
(El énfasis es mío)
Supongamos que tiene 2 variables no intercaladas . Por lo tanto, desea acceder a cada uno desde diferentes hilos al mismo tiempo. Debe definir el bloqueo no en la clase de objeto en sí, sino en la clase Objeto como se muestra a continuación (ejemplo del segundo enlace de Oracle):
fuente
El bloqueo al que se accede está en el objeto, no en el método. A qué variables se accede dentro del método es irrelevante.
Agregar "sincronizado" al método significa que el subproceso que ejecuta el código debe adquirir el bloqueo en el objeto antes de continuar. Agregar "estática sincronizada" significa que el hilo que ejecuta el código debe adquirir el bloqueo en el objeto de clase antes de continuar. Alternativamente, puede envolver el código en un bloque como este:
para que pueda especificar el objeto cuyo bloqueo debe ser adquirido.
Si desea evitar bloquear el objeto que lo contiene, puede elegir entre:
fuente
De la documentación de Oracle enlace de Oracle
Hacer métodos sincronizados tiene dos efectos:
Eche un vistazo a esta página de documentación para comprender los bloqueos intrínsecos y el comportamiento del bloqueo.
Esto responderá a su pregunta: en el mismo objeto x, no puede llamar a x.addA () y x.addB () al mismo tiempo cuando uno de los métodos sincronizados está en ejecución.
fuente
Si tiene algunos métodos que no están sincronizados y están accediendo y cambiando las variables de instancia. En tu ejemplo:
cualquier cantidad de subprocesos puede acceder a estos métodos no sincronizados al mismo tiempo cuando otro subproceso está en el método sincronizado del mismo objeto y puede realizar cambios en las variables de instancia. Por ejemplo: -
Debe evitar el escenario de que los métodos no sincronizados están accediendo a las variables de instancia y cambiándolas; de lo contrario, no tiene sentido utilizar métodos sincronizados.
En el siguiente escenario: -
Solo uno de los hilos puede estar en el método addA o addB, pero al mismo tiempo, cualquier número de hilos puede ingresar al método changeState. No hay dos subprocesos que puedan ingresar addA y addB al mismo tiempo (debido al bloqueo de nivel de objeto), pero al mismo tiempo cualquier cantidad de subprocesos puede ingresar changeState.
fuente
Puedes hacer algo como lo siguiente. En este caso, está utilizando el bloqueo en ayb para sincronizar en lugar del bloqueo en "esto". No podemos usar int porque los valores primitivos no tienen bloqueos, por lo que usamos Integer.
fuente
Sí, bloqueará el otro método porque el método sincronizado se aplica al objeto de clase WHOLE como se señala ... pero de todos modos bloqueará la ejecución del otro hilo SOLAMENTE mientras realiza la suma en cualquier método addA o addB que ingrese, porque cuando termine ... el hilo se LIBERAR el objeto y el otro hilo accederá a otro método y así sucesivamente perfecto estado de funcionamiento.
Quiero decir que el "sincronizado" está hecho precisamente para bloquear el acceso del otro hilo a otro mientras se ejecuta un código específico. FINALMENTE ESTE CÓDIGO FUNCIONARÁ BIEN.
Como nota final, si hay una variable 'a' y 'b', no solo una variable única 'a' o cualquier otro nombre, no hay necesidad de sincronizar estos métodos porque es perfectamente seguro acceder a otras var (Otra memoria ubicación).
Funcionará tan bien
fuente
Este ejemplo (aunque no es bonito) puede proporcionar más información sobre el mecanismo de bloqueo. Si Incrementa está sincronizado , y incrementB está no está sincronizado , entonces incrementB se ejecutará lo antes posible, pero si incrementB también se sincroniza entonces tiene que 'espera' para Incrementa hasta el final, antes de incrementB puede hacer su trabajo.
Ambos métodos se invocan en una sola instancia - objeto, en este ejemplo es: trabajo , y los hilos 'competidores' son aThread y main .
Pruebe con ' sincronizado ' en el incremento B y sin él y verá resultados diferentes. Si el incremento B también está ' sincronizado ', entonces tendrá que esperar a que termine el incremento A (). Ejecute varias veces cada variante.
fuente
En la sincronización de Java, si un subproceso desea ingresar al método de sincronización, se bloqueará en todos los métodos sincronizados de ese objeto, no solo en un método sincronizado que esté usando ese subproceso. Por lo tanto, un subproceso que ejecuta addA () adquirirá el bloqueo en addA () y addB () ya que ambos están sincronizados, por lo que otros subprocesos con el mismo objeto no pueden ejecutar addB ().
fuente
Esto podría no funcionar ya que el boxeo y el autoboxing de Integer a int y viceversa dependen de JVM y existe una alta posibilidad de que dos números diferentes se mezclen en la misma dirección si están entre -128 y 127.
fuente