java - sincronizar - Objeto de bloqueo estático frente a no estático en bloque sincronizado
sincronizar procesos java (1)
La diferencia es simple: si el objeto encerrado está en un campo static
, todas las instancias de MyClass*
compartirán ese bloqueo (es decir, no habrá dos objetos que puedan bloquear ese objeto al mismo tiempo).
Si el campo no es estático, cada instancia tendrá su propio bloqueo, por lo que solo las llamadas al método en el mismo objeto se bloquearán entre sí.
Cuando usas un objeto de bloqueo estático:
- el hilo 1 llama a
o1.foo()
- el hilo 2 llama a
o1.foo()
, tendrá que esperar a que termine el hilo 1 - el hilo 3 llama a
o2.foo()
, también tendrá que esperar a que termine el hilo 1 (y probablemente 2)
Cuando utiliza un objeto de bloqueo no estático:
- el hilo 1 llama a
o1.foo()
- el hilo 2 llama a
o1.foo()
, tendrá que esperar a que termine el hilo 1 - thread 3 llama a
o2.foo()
, simplemente puede continuar, sin importar el thread 1 y 2
El que necesite dependerá del tipo de datos que intente proteger con su bloque sincronizado.
Como regla general, quiere que el objeto de bloqueo tenga el mismo valor static
que el valor operado. Por lo tanto, si manipula solo valores no estáticos, querrá un objeto de bloqueo no estático. Si manipula solo valores estáticos, querrá un objeto de bloqueo estático.
Cuando manipulas valores estáticos y no estáticos , se volverá complicado. La manera más sencilla sería utilizar un objeto de bloqueo estático, pero eso podría aumentar el tamaño del bloque sincronizado más de lo absolutamente necesario y podría necesitar bloquear más la contención de lo deseado. En esos casos, es posible que necesite una combinación de objetos de bloqueo estáticos y no estáticos.
En su caso particular, utiliza el bloqueo en el constructor, que solo se ejecutará una vez por instancia, por lo que un objeto de bloqueo no estático no tiene sentido aquí.
Intentando visualizar y entender la sincronización .
- ¿Cuáles son las diferencias entre usar un objeto de bloqueo estático (código A) y un objeto de bloqueo no estático (código B) para un bloque sincronizado ?
- ¿Cómo difiere en las aplicaciones prácticas?
- ¿Cuáles son las dificultades que uno tendría que el otro no tendría?
- ¿Cuáles son los criterios para determinar cuál usar?
Código A
public class MyClass1 {
private static final Object lock = new Object();
public MyClass1() {
//unsync
synchronized(lock) {
//sync
}
//unsync
}
}
Código B
public class MyClass2 {
private final Object lock = new Object();
public MyClass2() {
//unsync
synchronized(lock) {
//sync
}
//unsync
}
}
Nota
El código anterior muestra constructores, pero podría hablar sobre cómo el comportamiento es diferente en un método estático y no también estático. Además, ¿sería ventajoso usar un bloqueo estático cuando el bloque sincronizado está modificando una variable miembro estática?
Ya miré las respuestas en esta pregunta , pero no está suficientemente claro cuáles son los diferentes escenarios de uso.