Pregunta

Los Tutoriales de Java dicen: "no es posible que dos invocaciones de métodos sincronizados en el mismo objeto se intercalen".

¿Qué significa esto para un método estático? 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?

¿Fue útil?

Solución

  

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í :)

Otros consejos

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 ejecutarse. Para un método de clase (estático), se utiliza el monitor asociado con el objeto Class para la clase del método. Para un método de instancia, se utiliza el monitor asociado con esto (el objeto para el que se invocó el método).

Un punto que debe tener cuidado (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 () yg () no están sincronizados entre sí y, por lo tanto, pueden ejecutarse de manera totalmente simultánea.

A menos que implemente g () de la siguiente manera:

g() {
    synchronized(getClass()) {
        ...
    }
}

Este patrón también me resulta útil cuando quiero implementar la exclusión mutua entre diferentes instancias del objeto (que es necesario cuando se accede a un recurso externo, por ejemplo).

Consulte la página de documentación de Oracle en Bloqueos intrínsecos y sincronización

  

Quizás se pregunte 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 de clase asociado con la clase . Por lo tanto, el acceso a los campos estáticos de la clase se controla mediante un bloqueo que es distinto del bloqueo para cualquier instancia de la clase .

Un método estático también tiene un objeto asociado. Pertenece al archivo Class.class en el kit de herramientas JDK. Cuando el archivo .class se carga en la memoria RAM, el Class.class crea una instancia llamada objeto de plantilla.

Por ejemplo: - cuando intenta crear un objeto a partir de una clase de cliente existente como

Customer c = new Customer();

La carga Customer.class en RAM. En ese momento Class.class en el kit de herramientas JDK crea un Objeto llamado Objeto Template y carga ese Customer.class en ese objeto template. Los miembros estáticos de ese Customer.class se convierten en atributos y métodos en ese objeto template.

Entonces, un método o atributo estático también tiene un objeto

Los ejemplos a continuación brindan más claridad entre la clase y el bloqueo de objetos, espero que el siguiente ejemplo ayude a otros también :)

Por ejemplo, tenemos los siguientes métodos: una clase de adquisición y otra bloqueo de objeto de adquisición:

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:

  1. Cuando los hilos que usan mismo Objeto intenta acceder al objLock O staticLock al 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
    
  2. Cuando los hilos que usan mismo Objeto intenta acceder a los métodos staticLock y objLock al 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
    
  3. Cuando los hilos que utilizan Objetos diferentes intentan acceder al método staticLock

    <*>
  4. Cuando los hilos que usan Objetos diferentes intentan acceder al método objLock

    <*>

Para aquellos que no están familiarizados con el método estático sincronizado bloqueado en un objeto de clase, p. para la clase de cadena, su String.class mientras que el método sincronizado de instancia se bloquea en la instancia actual de Object denotada por la palabra clave "this" en Java. Dado que ambos objetos son diferentes, tienen un bloqueo diferente, por lo que mientras un subproceso está ejecutando el método estático sincronizado, otro subproceso en Java no necesita esperar a que ese subproceso regrese, sino que adquirirá un bloqueo separado, el byte denotado .class literal y entrará en Método sincronizado estático.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top