Métodos estáticos sincronizados de Java: bloqueo de objeto o clase
class static (8)
Los Tutoriales de Java dicen: "no es posible intercalar dos invocaciones de métodos sincronizados en el mismo objeto".
¿Qué significa esto para un static method
? Dado que un método estático no tiene ningún objeto asociado, ¿se bloqueará la palabra clave sincronizada en la clase, en lugar del objeto?
Dado que un método estático no tiene ningún objeto asociado, ¿ se bloqueará la palabra clave sincronizada en la clase, en lugar del objeto?
Sí. :)
A continuación, los ejemplos brindan más claridad entre la clase y el bloqueo de objetos, el ejemplo siguiente esperanza ayudará a los demás también :)
Por ejemplo, tenemos los siguientes métodos una clase de adquisición y otro objeto de adquisición de bloqueo:
public class MultiThread {
public static synchronized void staticLock() throws InterruptedException {
for (int i = 0; i < 10; i++) {
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
public synchronized void objLock() throws InterruptedException {
for (int i = 0; i < 10; i++) {
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
}
Entonces, ahora podemos tener los siguientes escenarios:
Cuando los hilos que usan el mismo objeto intentan acceder al método
objLock
ORstaticLock
mismo tiempo (es decir, ambos hilos intentan acceder al mismo método)Thread-0 0 Thread-0 1 Thread-0 2 Thread-0 3 Thread-0 4 Thread-1 0 Thread-1 1 Thread-1 2 Thread-1 3 Thread-1 4
Cuando los hilos que usan el mismo objeto intentan acceder a los métodos
staticLock
yobjLock
mismo tiempo (intenta acceder a diferentes métodos)Thread-0 0 Thread-1 0 Thread-0 1 Thread-1 1 Thread-0 2 Thread-1 2 Thread-1 3 Thread-0 3 Thread-0 4 Thread-1 4
Cuando los hilos que usan diferentes objetos intentan acceder
staticLock
métodostaticLock
Thread-0 0 Thread-0 1 Thread-0 2 Thread-0 3 Thread-0 4 Thread-1 0 Thread-1 1 Thread-1 2 Thread-1 3 Thread-1 4
Cuando los hilos que usan diferentes objetos intentan acceder
objLock
métodoobjLock
Thread-0 0 Thread-1 0 Thread-0 1 Thread-1 1 Thread-0 2 Thread-1 2 Thread-1 3 Thread-0 3 Thread-0 4 Thread-1 4
A menos que implemente g () de la siguiente manera:
g() {
synchronized(getClass()) {
...
}
}
Encuentro este patrón útil también cuando quiero implementar la exclusión mutua entre diferentes instancias del objeto (que es necesario cuando accedo a un recurso externo, por ejemplo).
Eche un vistazo a la página de documentación de Oracle sobre bloqueos intrínsecos y sincronización
Puede preguntarse qué sucede cuando se invoca un método estático sincronizado, ya que un método estático está asociado a una clase, no a un objeto. En este caso, el hilo adquiere el bloqueo intrínseco para el objeto Class asociado a la clase . Por lo tanto, el acceso a los campos estáticos de la clase está controlado por un bloqueo que es distinto del bloqueo para cualquier instancia de la clase .
Hay que tener en cuenta un punto (varios programadores generalmente caen en esa trampa) es que no existe un vínculo entre los métodos estáticos sincronizados y los métodos no estáticos sincronizados, es decir:
class A {
static synchronized f() {...}
synchronized g() {...}
}
Principal:
A a = new A();
Tema 1:
A.f();
Tema 2:
a.g();
f () y g () no están sincronizados entre sí y, por lo tanto, se pueden ejecutar totalmente al mismo tiempo.
Para aquellos que no están familiarizados con el método estático sincronizado bloqueado en el objeto de la clase, por ejemplo, para la clase de cadena su String.class mientras que el método instancia sincronizada se bloquea en la instancia actual de Object denotada por "this" en Java. Dado que ambos objetos son diferentes, tienen un bloqueo diferente, por lo que mientras un hilo está ejecutando el método estático sincronizado, el otro hilo en Java no necesita esperar que el hilo vuelva a aparecer, sino que adquirirá el bloqueo por separado. método estático sincronizado
Solo para agregar un pequeño detalle a la respuesta de Oscar (¡agradablemente sucinta!), La sección relevante sobre la Especificación del lenguaje Java es 8.4.3.6, "Métodos sincronizados" :
Un método sincronizado adquiere un monitor (§17.1) antes de que se ejecute. Para un método de clase (estático), se usa el monitor asociado con el objeto de Clase para la clase del método. Para un método de instancia, se usa el monitor asociado con esto (el objeto para el cual se invocó el método).
Un método estático también tiene un objeto asociado. Pertenece al archivo Class.class en JDK toolkit. Cuando el archivo .class se carga en el ram, el Class.class crea una instancia del mismo llamada objeto de plantilla.
Por ejemplo: cuando intentas crear un objeto a partir de una clase de cliente existente como
Customer c = new Customer();
La carga de Customer.class en la RAM. En ese momento Class.class en JDK Toolkit crea un objeto llamado objeto Template y carga esa clase Customer.class en ese objeto template.Static miembros de ese Customer.class se convierten en atributos y métodos en ese objeto de plantilla.
Entonces, un método o atributo estático también tiene un objeto