2011-06-24 24 views

Respuesta

11

Un mecanismo de bloqueo de reentrada permite que la rosca que sujeta la cerradura vuelva a entrar en una sección crítica. Esto significa que usted puede hacer algo como esto:

public synchronized void functionOne() { 

    // do something 

    functionTwo(); 

    // do something else 

    // redundant, but permitted... 
    synchronized(this) { 
     // do more stuff 
    }  
} 

public synchronized void functionTwo() { 
    // do even more stuff! 
} 

En una cerradura no reentrante, que tendría una situación de bloqueo cuando intenta llamar desde functionTwo()functionOne() porque el hilo tendría que esperar a que el bloqueo .. .que se sostiene a sí mismo.

Deadlock, por supuesto, es la mala situación en la que el hilo 1 mantiene el bloqueo A y está esperando el bloqueo B mientras que el hilo 2 mantiene el bloqueo B y está esperando el bloqueo A. Por lo tanto, ninguno puede continuar. Este ejemplo de código crea un punto muerto:

hilo
public synchronized void deadlock() throws InterruptedException { 
    Thread th = new Thread() { 
     public void run() { 
      deadlock(); 
     } 
    }.start(); 

    th.join(); 
} 

La vocación trata de esperar a que el subproceso generado, que a su vez no puede llamar deadlock() hasta que el llamante ha salido. Ka-boom!

+0

Supongo que OP significa ejemplo usando la clase 'java.util.concurrent.locks.ReentrantLock' y no el bloque' synchronized'. –

+0

@Victor Sorokin no estoy seguro de si está destinado a la capitalización o no. sin embargo, el concepto de alto nivel es exactamente el mismo, ya sea usando bloques 'sincronizados' o la clase' ReentrantLock'. – stevevls

0

Un bloqueo de reentrada permitirá que el portador de la cerradura ingrese bloques de código incluso después de que ya haya obtenido la cerradura ingresando otros bloques de código. Un bloqueo no reentrante tendría el bloqueador de bloqueo bloqueándose sobre sí mismo, ya que tendría que liberar el bloqueo obtenido de otro bloque de código para volver a obtener ese mismo bloqueo para ingresar al bloqueo anidado que requiere bloque de código.

En lo que respecta al interbloqueo, si llama a un bloque de código protegido desde un bloque de código protegido, querrá un bloqueo de reentrada (o bloqueará mientras espera en sí mismo).

1

He aquí un ejemplo de estancamiento con ReentrantLock

class Deadlock { 
    private static final ReentrantLock l1 = new ReentrantLock(); 

    public static void main(String[] args) { 
     Thread t = new Thread(new Runnable() { 
      public void run() { 
       System.out.println("A Trying to lock..."); 
       l1.lock(); 
       System.out.println("A Locked..."); 
       try { 
        Thread t = new Thread(new Runnable() { 
         public void run() { 
          System.out.println("B Trying to lock..."); 
          l1.lock(); 
          System.out.println("B Must not print"); 
          try { 
          } finally { 
           System.out.println("B Trying to unlock..."); 
           l1.unlock(); 
           System.out.println("B Unlocked..."); 
          } 
         } 
        }); 
        t.start(); 
        try { 
         t.join(); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
       } finally { 
        System.out.println("A Trying to unlock..."); 
        l1.unlock(); 
        System.out.println("A Unlocked..."); 
       } 
      } 
     }); 
     t.start(); 
    } 
} 

Para resolver estancamiento, comente llamada a t.join, junto con encerrando try/catch.

6

Se produce un bloqueo muerto y un subproceso espera una condición que nunca se producirá.

El caso obvio es cuando intenta bloquear dos bloqueos, bloqueados en un orden diferente por diferentes hilos.

ReentrantLock lock1 = new ReentrantLock(); 
ReentrantLock lock2 = new ReentrantLock(); 

public void methodA() { 
    lock1.lock(); 
    lock2.lock(); 
    // do something and un lock both. 
} 

public void methodB() { 
    lock2.lock(); 
    lock1.lock(); 
    // do something and un lock both. 
} 

Como se puede ver que es posible que un hilo para llamar y obtener MethodA lock1 espera de Lock2, y otro hilo para llamar y obtener methodB Lock2 espera de lock1.


Sin embargo, es posible que un hilo de punto muerto en sí. Un ejemplo es ReentrantReadWriteLock porque no admite la actualización de un bloqueo de lectura para escribir el bloqueo.

ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); 
rwl.readLock().lock(); 
// do we need to update? 
rwl.writeLock().lock(); // will wait for the readLock() to be released! 

Una oportunidad oscura a un punto muerto a sí mismo es cuando cerraduras implicadas están utilizando. Un bloque inicializador estático está implícita hilo de seguridad por lo que un bloqueo se utiliza a pesar de que los bloques no son estáticas initialiser synchronized

class A { 
    private static int VALUE; 
    static { 
     Thread t = new Thread() { 
      public void run() { 
       // waits for the A class to load. 
       VALUE = someLongTask(); 
      } 
     }; 
     t.start(); 
     // waits for the thread. 
     t.join(); 
    } 
} 

vez que tienen un punto muerto!

Cuestiones relacionadas