2011-02-03 28 views
37

tengo este código en Java:anidada sincronizada palabra clave

public void doSomeThing() { 
     synchronized (this) { 
      doSomeThingElse(); 
     } 
    } 
    public void doSomeThingElse() { 
     synchronized (this) { 
      // do something else 
     } 
    } 

Puede este bloque de código? Quiero decir, ¿este código puede esperar para siempre?

Respuesta

47

Como el reentrante java documentation describes para bloqueo:

un hilo puede adquirir una cerradura que ya posee

El segundo bloque sincronizado está utilizando la misma cerradura y así será siempre utilizable ya que el bloqueo ya ha sido adquirido en el método externo.

No, no habrá un punto muerto.

1

El bloqueo ya está ejecutado por el hilo que ejecuta el método doSomething, por lo tanto, este subproceso puede ejecutar el método doSomethingElse.

Necesita dos objetos de bloqueo para crear una situación de interbloqueo. En su caso, solo hay uno, por lo tanto, es imposible crear un punto muerto.

+0

¿Quiere decir que el código [// hacer algo más] puede ejecutarse correctamente? –

+0

Bueno, debería ejecutarse correctamente ... si no es así, debería publicar todo el código necesario. –

+0

Quiere decir que el hilo ya tiene el bloqueo requerido para el método secound, por lo que no se bloqueará. – kasten

3

En un bloque sincronizado puede volver a adquirir un candado que ya posee. El proveedor de bloqueo (esto) será adquirido por el primer hilo para ingresar doSomething(). Luego, en el método doSomethingElse() lo volverá a adquirir.

¿La razón para hacer esto? Bueno, no hay nada que decir que no haya otro hilo que ingrese doSomethingElse desde otro lado. Esto evitará que cualquier código ejecute el bloque en doSomething() hasta que el hilo en doSomethingElse() haya liberado "this".

Editar Por cierto, puede bloquear ... y bloqueará la ejecución de cualquier subproceso que no posea el objeto de sincronización. Sin embargo, no será (como se publicó) un punto muerto.

0

El uso sincronizado en ambos casos this así que si el bloque sincronizado en doSomeThing se ejecuta, ya tiene el bloqueo para que pueda ejecutar el método doSomeThingElse.

Si el código es tan simple, que es equivalente a:

public synchronized void doSomeThing() { 
    doSomeThingElse(); 
} 
public synchronized void doSomeThingElse() { 
    // do something else 
} 
0

Usted ya ha tomado el bloqueo del monitor en la primera sincronizada. Siempre debe asegurarse de que el diseño de concurrencia no haga que el rendimiento tenga un gran impacto.

Una forma de garantizar esto es sincronizando solo los enunciados/código requeridos.

Digamos que ahora su código se verá algo como esto.

public void doSomeThing() 
{ 
    synchronized (this) 
    {    
    synchronized (this) 
    {    
     // do something else   
    }   
    }  
} 

Mientras que esto es lo que se requiere

public void doSomeThing() 
    { 
     doSomeThingElse();  
    } 
public void doSomeThingElse() 
{ 
synchronized (this) 
     {    
      // do something else   
     } 
} 
7

Si un hilo posee el bloqueo en this, voy a entrar en otra synchronized métodos/bloque como cuchillo caliente en mantequilla.

+7

¿Se dividirá mi objeto? Esa metáfora ... – Kissaki